Skip to content

Commit bf8fc9f

Browse files
ousmaneoberndthllpatrickmannlaura-b-g
authored
Implement entity share request for collection (#22945)
* Add "Valid" annotation to CreateEntityRequest#entity (#22820) Enables cascading validations. * Expose MongoCollection#findOneAndUpdate method with update pipeline (#22820) This is required to use update aggregation pipelines. * Add more helper methods to PluginModule (#22820) - addGRNTypeProvider - addCapabilityPermissions - addSyncedEntitiesResolver * Map USERS_READ and USERS_EDIT to capabilities (#22820) This makes it possible to create working grants for users/teams. * Expose another ObjectMapper constructor for testing (#22820) We need to be able to customize the GRN registry. * Fix TestUserService#loadByIds method (#22820) The given IDs must be converted to ObjectIDs. * checkpoint * add collections to create request * license header * use utility methods * adjust stream create to new api * adjust eventDefinition create to new endpoint - add create event definition hook * adjust event definition types * adjust Notication create to new api * adjust view endpoint to new API * fix linter * use pluggable entitshare form group * add hook * add license - renaming * update test * adjust label * rename hook * add collection binding for backend test * fix test * adjust tests for modified entity creation request * fix merge conflict * adjust more backend tests to modified signature * check for selected_grantee_capabilities * cleanup merge * upgrading.md and remove unneeded default implementation --------- Co-authored-by: Bernd Ahlers <[email protected]> Co-authored-by: Bernd Ahlers <[email protected]> Co-authored-by: Othello Maurer <[email protected]> Co-authored-by: patrickmann <[email protected]> Co-authored-by: Patrick Mann <[email protected]> Co-authored-by: Laura Bergenthal-Grotlüschen <[email protected]> Co-authored-by: Anton Ebel <[email protected]>
1 parent 337e8a4 commit bf8fc9f

File tree

44 files changed

+894
-540
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+894
-540
lines changed

UPGRADING.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,37 @@ can only talk to Kafka brokers with version 2.1 or newer.
2727

2828
- In Graylog 7.0, an issue was fixed that previously allowed additional unknown JSON properties to be accepted
2929
(and ignored) in API requests on the Graylog leader node. Now that the issue has been fixed, API requests on the
30-
leader node will once again only accept JSON payloads that contain explicitly mapped/supported properties.
30+
leader node will once again only accept JSON payloads that contain explicitly mapped/supported properties.
31+
- APIs for entity creation now use a parameter `CreateEntityRequest` to keep entity fields separated from sharing
32+
information. This is a breaking change for all API requests that create entities, such as streams, dashboards, etc.
33+
<br> Affected entities:
34+
- Search / Dashboard
35+
- Search Filter
36+
- Report
37+
- Event Definition
38+
- Stream
39+
- Notifications
40+
- Sigma rules
41+
- Event procedure
42+
- Event step
43+
44+
<br> For example, the request payload to create a stream might now look like this:
45+
46+
```json
47+
{
48+
"entity":{
49+
"index_set_id":"65b7ba138cdb8c534a953fef",
50+
"description":"An example stream",
51+
"title":"My Stream",
52+
"remove_matches_from_default_stream":false
53+
},
54+
"share_request":{
55+
"selected_grantee_capabilities":{
56+
"grn::::search:684158906442150b2eefb78c":"own"
57+
}
58+
}
59+
}
60+
```
3161

3262
## REST API Endpoint Changes
3363

@@ -36,3 +66,4 @@ The following REST API changes have been made.
3666
| Endpoint | Description |
3767
|-----------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
3868
| `GET /<endpoint>` | description |
69+
| `GET /<endpoint>` | description |

full-backend-tests/src/test/java/org/graylog/exceptionmappers/JsonParsingErrorsIT.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,15 @@ void returnsSpecificErrorForJsonParsingError() {
101101
@ContainerMatrixTest
102102
void extractsReferencePathFromMissingProperty() {
103103
assertErrorResponse(STREAMS, "{}")
104-
.body("reference_path", equalTo("org.graylog2.rest.resources.streams.requests.CreateStreamRequest"));
104+
.body("reference_path", equalTo("org.graylog.security.shares.CreateEntityRequest"));
105105

106106
assertErrorResponse(STREAMS, """
107107
{
108108
"title": "Foo",
109109
"rules": [{}]
110110
}
111111
""")
112-
.body("reference_path", equalTo(
113-
"org.graylog2.rest.resources.streams.requests.CreateStreamRequest[\"rules\"]" +
114-
"->java.util.ArrayList[0]" +
115-
"->org.graylog2.rest.resources.streams.rules.requests.CreateStreamRuleRequest"));
112+
.body("reference_path", equalTo("org.graylog.security.shares.CreateEntityRequest"));
116113
}
117114

118115
@ContainerMatrixTest

full-backend-tests/src/test/java/org/graylog/testing/utils/StreamUtils.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import com.fasterxml.jackson.annotation.JsonProperty;
2020
import io.restassured.response.ValidatableResponse;
2121
import io.restassured.specification.RequestSpecification;
22-
import org.graylog.testing.completebackend.apis.GraylogApis;
22+
import org.graylog.security.shares.CreateEntityRequest;
2323

2424
import java.util.Collection;
2525
import java.util.List;
@@ -41,7 +41,8 @@ record CreateStreamRequest(@JsonProperty("title") String title,
4141
@JsonProperty("index_set_id") String indexSetId) {}
4242

4343
public static String createStream(Supplier<RequestSpecification> spec, String title, String indexSetId, StreamRule... streamRules) {
44-
final CreateStreamRequest body = new CreateStreamRequest(title, List.of(streamRules), indexSetId);
44+
final CreateEntityRequest<CreateStreamRequest> body = CreateEntityRequest.create(
45+
new CreateStreamRequest(title, List.of(streamRules), indexSetId), null);
4546
final String streamId = given()
4647
.spec(spec.get())
4748
.when()
Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,44 @@
11
{
2-
"id": "6141d45bd3a6b9d73c8ac55c",
3-
"type": "DASHBOARD",
4-
"title": "test",
5-
"search_id": "6141d457d3a6b9d73c8ac55b",
6-
"state": {
7-
"278992f6-8930-43f5-9dd7-11bbc4e3b797": {
8-
"titles": {},
9-
"widgets": [
10-
{
11-
"id": "34316a67-3dca-4994-a061-2fc6a9bf7f0b",
12-
"type": "logs",
13-
"config": {
14-
"fields": [
15-
"timestamp",
16-
"source",
17-
"message"
18-
],
19-
"size": 100,
20-
"sort": "DESC"
21-
},
22-
"streams": []
23-
}
24-
],
25-
"widget_mapping": {
26-
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": [
27-
"967d2217-fd99-48a6-b829-5acdab906807"
28-
]
29-
},
30-
"positions": {
31-
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": {
32-
"col": 1,
33-
"row": 1,
34-
"height": 4,
35-
"width": 12
2+
"entity":
3+
{
4+
"id": "6141d45bd3a6b9d73c8ac55c",
5+
"type": "DASHBOARD",
6+
"title": "test",
7+
"search_id": "6141d457d3a6b9d73c8ac55b",
8+
"state": {
9+
"278992f6-8930-43f5-9dd7-11bbc4e3b797": {
10+
"titles": {},
11+
"widgets": [
12+
{
13+
"id": "34316a67-3dca-4994-a061-2fc6a9bf7f0b",
14+
"type": "logs",
15+
"config": {
16+
"fields": [
17+
"timestamp",
18+
"source",
19+
"message"
20+
],
21+
"size": 100,
22+
"sort": "DESC"
23+
},
24+
"streams": []
25+
}
26+
],
27+
"widget_mapping": {
28+
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": [
29+
"967d2217-fd99-48a6-b829-5acdab906807"
30+
]
31+
},
32+
"positions": {
33+
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": {
34+
"col": 1,
35+
"row": 1,
36+
"height": 4,
37+
"width": 12
38+
}
3639
}
3740
}
38-
}
39-
},
40-
"created_at": "2021-09-15T11:08:42.248Z"
41+
},
42+
"created_at": "2021-09-15T11:08:42.248Z"
43+
}
4144
}
Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
{
2-
"id": "6141d45bd3a6b9d73c8ac55b",
3-
"type": "DASHBOARD",
4-
"title": "test",
5-
"search_id": "6141d457d3a6b9d73c8ac55c",
6-
"state": {
7-
"278992f6-8930-43f5-9dd7-11bbc4e3b797": {
8-
"titles": {},
9-
"widgets": [
10-
{
11-
"id": "34316a67-3dca-4994-a061-2fc6a9bf7f0b",
12-
"type": "logs",
13-
"config": {
14-
"fields": [
15-
"timestamp",
16-
"source",
17-
"message"
18-
],
19-
"size": 100,
20-
"sort": "DESC"
21-
},
22-
"streams": []
23-
}
24-
],
25-
"widget_mapping": {
26-
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": [
27-
"967d2217-fd99-48a6-b829-5acdab906808"
28-
]
29-
},
30-
"positions": {
31-
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": {
32-
"col": 1,
33-
"row": 1,
34-
"height": 4,
35-
"width": 12
2+
"entity": {
3+
"id": "6141d45bd3a6b9d73c8ac55b",
4+
"type": "DASHBOARD",
5+
"title": "test",
6+
"search_id": "6141d457d3a6b9d73c8ac55c",
7+
"state": {
8+
"278992f6-8930-43f5-9dd7-11bbc4e3b797": {
9+
"titles": {},
10+
"widgets": [
11+
{
12+
"id": "34316a67-3dca-4994-a061-2fc6a9bf7f0b",
13+
"type": "logs",
14+
"config": {
15+
"fields": [
16+
"timestamp",
17+
"source",
18+
"message"
19+
],
20+
"size": 100,
21+
"sort": "DESC"
22+
},
23+
"streams": []
24+
}
25+
],
26+
"widget_mapping": {
27+
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": [
28+
"967d2217-fd99-48a6-b829-5acdab906808"
29+
]
30+
},
31+
"positions": {
32+
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": {
33+
"col": 1,
34+
"row": 1,
35+
"height": 4,
36+
"width": 12
37+
}
3638
}
3739
}
38-
}
39-
},
40-
"created_at": "2021-09-15T11:08:42.248Z"
40+
},
41+
"created_at": "2021-09-15T11:08:42.248Z"
42+
}
4143
}
Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
{
2-
"id": "6141d45bd3a6b9d73c8ac55b",
3-
"type": "DASHBOARD",
4-
"title": "test",
5-
"search_id": "6141d457d3a6b9d73c8ac55a",
6-
"state": {
7-
"278992f6-8930-43f5-9dd7-11bbc4e3b797": {
8-
"titles": {},
9-
"widgets": [
10-
{
11-
"id": "34316a67-3dca-4994-a061-2fc6a9bf7f0b",
12-
"type": "logs",
13-
"config": {
14-
"fields": [
15-
"timestamp",
16-
"source",
17-
"message"
18-
],
19-
"size": 100,
20-
"sort": "DESC"
21-
},
22-
"streams": []
23-
}
24-
],
25-
"widget_mapping": {
26-
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": [
27-
"967d2217-fd99-48a6-b829-5acdab906807"
28-
]
29-
},
30-
"positions": {
31-
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": {
32-
"col": 1,
33-
"row": 1,
34-
"height": 4,
35-
"width": 12
2+
"entity": {
3+
"id": "6141d45bd3a6b9d73c8ac55b",
4+
"type": "DASHBOARD",
5+
"title": "test",
6+
"search_id": "6141d457d3a6b9d73c8ac55a",
7+
"state": {
8+
"278992f6-8930-43f5-9dd7-11bbc4e3b797": {
9+
"titles": {},
10+
"widgets": [
11+
{
12+
"id": "34316a67-3dca-4994-a061-2fc6a9bf7f0b",
13+
"type": "logs",
14+
"config": {
15+
"fields": [
16+
"timestamp",
17+
"source",
18+
"message"
19+
],
20+
"size": 100,
21+
"sort": "DESC"
22+
},
23+
"streams": []
24+
}
25+
],
26+
"widget_mapping": {
27+
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": [
28+
"967d2217-fd99-48a6-b829-5acdab906807"
29+
]
30+
},
31+
"positions": {
32+
"34316a67-3dca-4994-a061-2fc6a9bf7f0b": {
33+
"col": 1,
34+
"row": 1,
35+
"height": 4,
36+
"width": 12
37+
}
3638
}
3739
}
38-
}
39-
},
40-
"created_at": "2021-09-15T11:08:42.248Z"
40+
},
41+
"created_at": "2021-09-15T11:08:42.248Z"
42+
}
4143
}

graylog2-server/src/main/java/org/graylog/events/rest/EventDefinitionsResource.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@
6666
import org.graylog.plugins.views.startpage.recentActivities.RecentActivityService;
6767
import org.graylog.scheduler.schedule.CronUtils;
6868
import org.graylog.security.UserContext;
69+
import org.graylog.security.shares.CreateEntityRequest;
6970
import org.graylog.security.shares.EntitySharesService;
70-
import org.graylog.security.shares.UnwrappedCreateEntityRequest;
7171
import org.graylog2.audit.AuditEventSender;
7272
import org.graylog2.audit.jersey.AuditEvent;
7373
import org.graylog2.audit.jersey.NoAuditEvent;
@@ -281,8 +281,8 @@ public List<EventDefinitionDto> getById(@ApiParam(name = "JSON body") @Valid Get
281281
@AuditEvent(type = EventsAuditEventTypes.EVENT_DEFINITION_CREATE)
282282
@RequiresPermissions(RestPermissions.EVENT_DEFINITIONS_CREATE)
283283
public Response create(@ApiParam("schedule") @QueryParam("schedule") @DefaultValue("true") boolean schedule,
284-
@ApiParam(name = "JSON Body") UnwrappedCreateEntityRequest<EventDefinitionDto> unwrappedCreateEntityRequest, @Context UserContext userContext) {
285-
final EventDefinitionDto dto = unwrappedCreateEntityRequest.getEntity();
284+
@ApiParam(name = "JSON Body") CreateEntityRequest<EventDefinitionDto> createEntityRequest, @Context UserContext userContext) {
285+
final EventDefinitionDto dto = createEntityRequest.entity();
286286
checkEventDefinitionPermissions(dto, "create");
287287

288288
final ValidationResult result = dto.validate(null, eventDefinitionConfiguration, userContext);
@@ -293,7 +293,7 @@ public Response create(@ApiParam("schedule") @QueryParam("schedule") @DefaultVal
293293
eventDefinitionHandler.create(dto, Optional.of(userContext.getUser())) :
294294
eventDefinitionHandler.createWithoutSchedule(dto.toBuilder().state(EventDefinition.State.DISABLED).build(), Optional.of(userContext.getUser()));
295295
recentActivityService.create(entity.id(), GRNTypes.EVENT_DEFINITION, userContext.getUser());
296-
unwrappedCreateEntityRequest.getShareRequest().ifPresent(shareRequest -> {
296+
createEntityRequest.shareRequest().ifPresent(shareRequest -> {
297297
entitySharesService.updateEntityShares(GRNTypes.EVENT_DEFINITION, entity.id(), shareRequest, userContext.getUser());
298298
});
299299

graylog2-server/src/main/java/org/graylog/events/rest/EventNotificationsResource.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@
5050
import org.graylog.grn.GRNTypes;
5151
import org.graylog.plugins.views.startpage.recentActivities.RecentActivityService;
5252
import org.graylog.security.UserContext;
53+
import org.graylog.security.shares.CreateEntityRequest;
5354
import org.graylog.security.shares.EntitySharesService;
54-
import org.graylog.security.shares.UnwrappedCreateEntityRequest;
5555
import org.graylog2.alarmcallbacks.EmailAlarmCallback;
5656
import org.graylog2.audit.jersey.AuditEvent;
5757
import org.graylog2.audit.jersey.NoAuditEvent;
@@ -185,8 +185,8 @@ public NotificationDto get(@ApiParam(name = "notificationId") @PathParam("notifi
185185
@ApiOperation("Create new notification definition")
186186
@AuditEvent(type = EventsAuditEventTypes.EVENT_NOTIFICATION_CREATE)
187187
@RequiresPermissions(RestPermissions.EVENT_NOTIFICATIONS_CREATE)
188-
public Response create(@ApiParam(name = "JSON Body") UnwrappedCreateEntityRequest<NotificationDto> unwrappedCreateEntityRequest, @Context UserContext userContext) {
189-
final NotificationDto dto = unwrappedCreateEntityRequest.getEntity();
188+
public Response create(@ApiParam(name = "JSON Body") CreateEntityRequest<NotificationDto> createEntityRequest, @Context UserContext userContext) {
189+
final NotificationDto dto = createEntityRequest.entity();
190190
final ValidationResult validationResult = dto.validate();
191191
validateEmailConfiguration(dto, validationResult);
192192
if (validationResult.failed()) {
@@ -195,7 +195,7 @@ public Response create(@ApiParam(name = "JSON Body") UnwrappedCreateEntityReques
195195
var entity = resourceHandler.create(dto, java.util.Optional.ofNullable(userContext.getUser()));
196196
recentActivityService.create(entity.id(), GRNTypes.EVENT_NOTIFICATION, userContext.getUser());
197197

198-
unwrappedCreateEntityRequest.getShareRequest().ifPresent(shareRequest -> {
198+
createEntityRequest.shareRequest().ifPresent(shareRequest -> {
199199
entitySharesService.updateEntityShares(GRNTypes.EVENT_NOTIFICATION, entity.id(), shareRequest, userContext.getUser());
200200
});
201201

graylog2-server/src/main/java/org/graylog/grn/GRN.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ static GRN parse(String grn, GRNRegistry grnRegistry) {
7171
return builder.build();
7272
}
7373

74+
public boolean isType(GRNType grnType) {
75+
return this.grnType().equals(grnType);
76+
}
77+
7478
public static Builder builder() {
7579
return new AutoValue_GRN.Builder().cluster("").tenant("").scope("");
7680
}

0 commit comments

Comments
 (0)