Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new endpoint checkpermissions #2047

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ entries:
- title: Authentication and Authorization
url: /basic-auth.html
output: web
subfolders:
- title: Checking Permissions for Resources
url: /check-permissions.html
output: web
- title: Messages
url: /basic-messages.html
output: web
Expand Down
62 changes: 62 additions & 0 deletions documentation/src/main/resources/openapi/ditto-api-2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6567,6 +6567,31 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/AdvancedError'
/api/2/checkPermissions:
post:
summary: "Check Permissions for Resources"
description: "An endpoint to verify permissions on specified resources."
tags:
- Policies
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PermissionCheckRequest'
responses:
'200':
description: "Permissions check result"
content:
application/json:
schema:
$ref: '#/components/schemas/PermissionCheckResponse'
'401':
description: The request could not be completed due to missing authentication.
content:
application/json:
schema:
$ref: '#/components/schemas/AdvancedError'
/api/2/search/things:
get:
summary: Search for things
Expand Down Expand Up @@ -10430,6 +10455,43 @@ components:
- security
- securityDefinitions
additionalProperties: true
PermissionCheckRequest:
type: object
description: "Request to check permissions for various entities and resources."
additionalProperties:
$ref: '#/components/schemas/PermissionEntityCheck'
example:
lamp_reader:
resource: "thing:/features/lamp/properties/on"
entityId: "org.eclipse.ditto:some-thing-1"
hasPermissions: [ "READ" ]
lamp_toggler:
resource: "message:/features/lamp/inbox/toggle"
entityId: "org.eclipse.ditto:some-thing-1"
hasPermissions: [ "WRITE" ]
PermissionEntityCheck:
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
description: "Required permissions on the resource."
PermissionCheckResponse:
type: object
description: "Response with permission check results for each entity."
additionalProperties:
type: boolean
example:
lamp_reader: true
lamp_toggler: false
TextUnauthorizeError:
type: string
example: The supplied authentication is invalid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ paths:
'/api/2/whoami':
$ref: "./paths/whoami/index.yml"

###
### Check Permissions
###
'/api/2/checkPermissions':
$ref: "./paths/checkPermissions/index.yml"

###
### Things-Search
###
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright (c) 2024 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
post:
summary: Check permissions for specified entities
description: |-
This endpoint allows you to verify permissions for various entities on specific resources.
tags:
- Policies
requestBody:
description: JSON payload containing entities and their permissions to be checked.
required: true
content:
application/json:
schema:
$ref: '../../schemas/checkPermissions/permissionCheckRequest.yml'
responses:
'200':
description: Permission check results for each entity.
content:
application/json:
schema:
$ref: '../../schemas/checkPermissions/permissionCheckResponse.yml'
'401':
description: Unauthorized request due to missing authentication.
content:
application/json:
schema:
$ref: '../../schemas/errors/advancedError.yml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2024 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: |-
Request to check permissions for various entities and resources.
additionalProperties:
$ref: 'permissionEntityCheck.yml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2024 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: "Response with permission check results for each entity."
additionalProperties:
type: boolean
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) 2024 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: |-
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."
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: Checking Permissions for Resources
keywords: permissions, authorization, resources, policy, checkPermissions
tags: [model]
permalink: check-permissions.html
---

The `/checkPermissions` endpoint allows clients to validate permissions for various entities and resources.

## Overview

The `/checkPermissions` endpoint is part of Ditto's HTTP API, enhancing its policy-based authorization system by enabling permission validation checks on resources without modifying them.
This functionality is valuable for UI-driven applications, where permissions checks can determine whether certain UI elements should be displayed or disabled based on the user’s access rights.

## Request Structure

Submit a `POST` request with a JSON payload specifying entities, resources, and permissions:

```json
{
"entity_name": {
"resource": "resource_path",
"entityId": "thingId",
"hasPermissions": ["READ", "WRITE"]
}
}
```
- entity_name: Name representing the entity.
- resource: Path of the target resource (e.g., thing:/features/light/properties/on).
- entityId: Unique identifier for the entity (thingId).
- hasPermissions: List of permissions required (READ, WRITE).
-
## Response Structure
The response indicates permission status for each entity and resource, returning a JSON object mapping entities to true (authorized) or false (unauthorized) values.

```json
{
"entity_name": true
}
```
This endpoint is especially useful for applications requiring quick permission validation for multiple entities across various resources.
26 changes: 25 additions & 1 deletion documentation/src/main/resources/pages/ditto/httpapi-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ managed.

In the HTTP API, some endpoints are static and can be seen as the "schema" of Ditto. They are in sync with the JSON
representation of the model classes, e.g. [Thing](basic-thing.html#model-specification) for the layout of the `/things`
endpoint and [Policy](basic-policy.html) for the layout of the `/policies` endpoint.
endpoint and [Policy](basic-policy.html) for the layout of the `/policies` endpoint, and `/checkPermissions` for verifying
access rights of entities on specific resources based on defined policies.

### API version 2

Expand Down Expand Up @@ -138,6 +139,29 @@ This maps to the following HTTP API endpoints:
* `/policies/{policyId}/entries/{entryLabel-1}/resources`: accessing the resources of a single `Policy` entry with the
label `{entryLabel-1}`

#### `/checkPermissions` in API 2
The checkPermissions endpoint verifies permissions for specified entities on various resources, ensuring they have the necessary access rights as defined in the policies.

```json
{
"lamp_reader": {
"resource": "thing:/features/lamp/properties/on",
"entityId": "org.eclipse.ditto:some-thing-1",
"hasPermissions": [
"READ"
]
},
"lamp_toggler": {
"resource": "message:/features/lamp/inbox/toggle",
"entityId": "org.eclipse.ditto:some-thing-1",
"hasPermissions": [
"WRITE"
]
}
}
```
The response will confirm if each entity has the requested permissions.

#### `/connections` in API 2

The base endpoint for accessing and working with `Connections`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
import org.eclipse.ditto.internal.utils.config.ScopedConfig;
import org.eclipse.ditto.messages.model.signals.commands.MessageCommand;
import org.eclipse.ditto.messages.model.signals.commands.MessageCommandResponse;
import org.eclipse.ditto.policies.api.commands.sudo.CheckPolicyPermissions;
import org.eclipse.ditto.policies.model.PolicyConstants;
import org.eclipse.ditto.policies.model.signals.commands.PolicyCommand;
import org.eclipse.ditto.things.api.commands.sudo.SudoRetrieveThing;
import org.eclipse.ditto.things.api.commands.sudo.SudoRetrieveThings;
import org.eclipse.ditto.things.model.ThingConstants;
import org.eclipse.ditto.things.model.signals.commands.ThingCommand;
Expand Down Expand Up @@ -144,7 +146,9 @@ public Receive createReceive() {
)
.match(RetrieveThings.class, this::forwardToThingsAggregatorProxy)
.match(SudoRetrieveThings.class, this::forwardToThingsAggregatorProxy)
.match(SudoRetrieveThing.class, this::forwardToThings)
.match(PolicyCommand.class, this::forwardToPolicies)
.match(CheckPolicyPermissions.class, this::forwardToPolicies)
.match(RetrieveAllConnectionIds.class, this::forwardToConnectivityPubSub)
.match(ConnectivityCommand.class, this::forwardToConnectivity)
.match(ConnectivitySudoCommand.class, this::forwardToConnectivity)
Expand Down Expand Up @@ -291,6 +295,7 @@ private void forwardToThingSearch(final Command<?> command) {
pubSubMediator.tell(DistPubSubAccess.send(ThingsSearchConstants.SEARCH_ACTOR_PATH, command), getSender());
}


private void handleUnknownSignal(final Signal<?> signal) {
applySignalTransformation(signal, sender())
.thenAccept(transformedSignal -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import org.eclipse.ditto.edge.service.acknowledgements.things.ThingLiveCommandAckRequestSetter;
import org.eclipse.ditto.edge.service.acknowledgements.things.ThingModifyCommandAckRequestSetter;
import org.eclipse.ditto.gateway.api.GatewayServiceUnavailableException;
import org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions.CheckPermissions;
import org.eclipse.ditto.gateway.service.endpoints.routes.whoami.DefaultUserInformation;
import org.eclipse.ditto.gateway.service.endpoints.routes.whoami.Whoami;
import org.eclipse.ditto.gateway.service.endpoints.routes.whoami.WhoamiResponse;
Expand Down Expand Up @@ -236,6 +237,7 @@ public AbstractActor.Receive handleMessage() {
}
})
.match(Whoami.class, this::handleWhoami)
.match(CheckPermissions.class, this::handleCheckPermissions)
.match(DittoRuntimeException.class, this::handleDittoRuntimeException)
.match(ReceiveTimeout.class,
receiveTimeout -> {
Expand Down Expand Up @@ -346,6 +348,14 @@ private void rememberResponseLocationUri(final CommandResponse<?> commandRespons
}
}

private void handleCheckPermissions(final CheckPermissions command) {
final ActorRef checkPermissionsActor = getContext().actorOf(
CheckPermissionsActor.props(proxyActor, getSelf(), getReceiveTimeout(command, commandConfig))
);
getContext().become(getResponseAwaitingBehavior());
checkPermissionsActor.tell(command, getSelf());
}

private void handleWhoami(final Whoami command) {
logger.withCorrelationId(command).debug("Got <{}>.", command);

Expand Down
Loading
Loading