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 15 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: /basic-auth-checkpermissions.html
output: web
- title: Messages
url: /basic-messages.html
output: web
Expand Down
64 changes: 64 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,45 @@ 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/messages/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
pattern: "^(thing|message|policy):(/[a-zA-Z0-9._-]+)*$"
description: "Resource key to be checked, beginning with 'thing:', 'message:', or 'policy:', followed by the specific resource path. This defines the scope of the permission request."
entityId:
type: string
description: "ID of the entity performing the action, which could be a ThingId or PolicyId, depending on the resource context."
hasPermissions:
type: array
items:
type: string
enum: [ "READ", "WRITE" ]
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,48 @@
---
title: Checking Permissions for Resources
keywords: permissions, authorization, resources, policy, checkPermissions
tags: [model]
permalink: basic-auth-checkpermissions.html
---

The `/checkPermissions` endpoint allows clients to validate permissions for specified entities on various resources, verifying access rights as defined in Ditto's policies.

## 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": "thing:/features/lamp/properties/on",
"entityId": "org.eclipse.ditto:some-thing-1",
"hasPermissions": ["READ"]
},
"another_entity": {
"resource": "message:/features/lamp/inbox/messages/toggle",
"entityId": "org.eclipse.ditto:some-thing-2",
"hasPermissions": ["WRITE"]
}
}
```
## Fields
- entity_name: Identifier for the entity performing the action.
- resource: Path of the target resource, starting with thing:, message:, or policy: followed by a valid resource path.
- entityId: Unique identifier for the entity, such as a thingId or policyId, depending on the resource.
- hasPermissions: Array of required permissions, such as READ or 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,
"another_entity": false
}
```
This endpoint is especially useful for applications requiring quick permission validation for multiple entities across various resources.
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
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