Skip to content

Commit 010c269

Browse files
committed
Merge branch 'master' of github.com:Graylog2/graylog2-server into feat/sigma-rules-import-summary-step
2 parents 78ddbd2 + 39310ef commit 010c269

106 files changed

Lines changed: 2865 additions & 613 deletions

File tree

Some content is hidden

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

UPGRADING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ After upgrading:
1818
matched only `test` now also matches `Test` and `TEST`. API clients relying on exact-case matching
1919
via paginated endpoints will see additional results.
2020

21+
## Java API Changes
22+
23+
| File/method | Description |
24+
|---------------------------------------------------------------------------|-------------|
25+
| `org.graylog2.contentpacks.facades.EntityWithExcerptFacade#resolveGrants` | removed |
26+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type = "f"
2+
message = "Fix false `Message failed to process` errors when a pipeline rule or extractor assigns a string `timestamp` field in ISO-8601 format. Such timestamps are now parsed leniently instead of being recorded as a processing failure."
3+
4+
issues = ["26025"]
5+
pulls = ["26269"]

changelog/unreleased/pr-26008.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type = "fixed" # One of: a(dded), c(hanged), d(eprecated), r(emoved), f(ixed), s(ecurity)
2+
message = "Fix MCP server 500 error on unknown client capability fields"
3+
4+
issues = ["25956"]
5+
pulls = ["26008"]

changelog/unreleased/pr-26161.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type = "a"
2+
message = "Include pipeline processing-load snapshot in support bundles."
3+
4+
issues = ["Graylog2/graylog-plugin-enterprise#14145"]
5+
pulls = ["26161"]

changelog/unreleased/pr-26244.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type = "f"
2+
message = "Fix Inputs Metrics telemetry not being reported."
3+
4+
pulls = ["26244"]

changelog/unreleased/pr-26268.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type = "f"
2+
message = "Replaying a dashboard widget again opens the replayed search in a new browser tab, keeping the dashboard open."
3+
pulls = ["26268"]

changelog/unreleased/pr-26284.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type = "s"
2+
message = "Check display field read permissions when resolving entity titles."
3+
pulls = ["26284"]

changelog/unreleased/pr-26296.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type = "f"
2+
message = "Fixed broken GreyNoise Quick IP Data Adapter by migrating to v3 API endpoint."
3+
pulls = ["26296"]

graylog2-server/src/main/java/org/graylog/events/contentpack/facade/EventDefinitionFacade.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@
3131
import org.graylog.events.processor.EventDefinitionDto;
3232
import org.graylog.events.processor.EventDefinitionHandler;
3333
import org.graylog.events.processor.EventProcessorExecutionJob;
34-
import org.graylog.grn.GRNTypes;
3534
import org.graylog.scheduler.DBJobDefinitionService;
3635
import org.graylog.scheduler.JobDefinitionDto;
37-
import org.graylog.security.GrantDTO;
38-
import org.graylog.security.shares.EntityGrantLookup;
3936
import org.graylog2.contentpacks.EntityDescriptorIds;
4037
import org.graylog2.contentpacks.facades.EntityFacade;
4138
import org.graylog2.contentpacks.facades.UpdatableEntityFacade;
@@ -58,7 +55,6 @@
5855
import org.slf4j.Logger;
5956
import org.slf4j.LoggerFactory;
6057

61-
import java.util.List;
6258
import java.util.Map;
6359
import java.util.Optional;
6460
import java.util.Set;
@@ -73,23 +69,20 @@ public class EventDefinitionFacade implements EntityFacade<EventDefinitionDto>,
7369
private final DBEventDefinitionService eventDefinitionService;
7470
private final Set<PluginMetaData> pluginMetaData;
7571
private final UserService userService;
76-
private final EntityGrantLookup grantLookup;
7772

7873
@Inject
7974
public EventDefinitionFacade(ObjectMapper objectMapper,
8075
EventDefinitionHandler eventDefinitionHandler,
8176
Set<PluginMetaData> pluginMetaData,
8277
DBJobDefinitionService jobDefinitionService,
8378
DBEventDefinitionService eventDefinitionService,
84-
UserService userService,
85-
EntityGrantLookup grantLookup) {
79+
UserService userService) {
8680
this.objectMapper = objectMapper;
8781
this.pluginMetaData = pluginMetaData;
8882
this.eventDefinitionHandler = eventDefinitionHandler;
8983
this.jobDefinitionService = jobDefinitionService;
9084
this.eventDefinitionService = eventDefinitionService;
9185
this.userService = userService;
92-
this.grantLookup = grantLookup;
9386
}
9487

9588
@VisibleForTesting
@@ -251,11 +244,6 @@ public boolean usesScopedEntities() {
251244
return true;
252245
}
253246

254-
@Override
255-
public List<GrantDTO> resolveGrants(EventDefinitionDto nativeEntity) {
256-
return grantLookup.getGrantsForTarget(GRNTypes.EVENT_DEFINITION, nativeEntity.id());
257-
}
258-
259247
@Override
260248
public Optional<EntityPermissions> getCreatePermissions(Entity entity) {
261249
return EntityPermissions.of(RestPermissions.EVENT_DEFINITIONS_CREATE);

graylog2-server/src/main/java/org/graylog/integrations/dataadapters/GreyNoiseQuickIPDataAdapter.java

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919
import com.codahale.metrics.MetricRegistry;
2020
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2121
import com.fasterxml.jackson.annotation.JsonCreator;
22+
import com.fasterxml.jackson.annotation.JsonIgnore;
2223
import com.fasterxml.jackson.annotation.JsonInclude;
2324
import com.fasterxml.jackson.annotation.JsonProperty;
24-
import com.fasterxml.jackson.annotation.JsonIgnore;
2525
import com.fasterxml.jackson.annotation.JsonTypeName;
26+
import com.fasterxml.jackson.databind.JsonNode;
27+
import com.fasterxml.jackson.databind.ObjectMapper;
2628
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
2729
import com.google.auto.value.AutoValue;
2830
import com.google.common.annotations.VisibleForTesting;
2931
import com.google.common.collect.Maps;
3032
import com.google.inject.assistedinject.Assisted;
31-
import com.unboundid.util.json.JSONException;
32-
import com.unboundid.util.json.JSONObject;
33+
import jakarta.annotation.Nonnull;
34+
import jakarta.inject.Inject;
35+
import jakarta.validation.constraints.NotEmpty;
3336
import okhttp3.OkHttpClient;
3437
import okhttp3.Request;
3538
import okhttp3.Response;
@@ -47,10 +50,6 @@
4750
import org.slf4j.Logger;
4851
import org.slf4j.LoggerFactory;
4952

50-
import jakarta.annotation.Nonnull;
51-
import jakarta.inject.Inject;
52-
import jakarta.validation.constraints.NotEmpty;
53-
5453
import java.io.IOException;
5554
import java.util.Map;
5655
import java.util.Objects;
@@ -59,12 +58,14 @@
5958
public class GreyNoiseQuickIPDataAdapter extends LookupDataAdapter {
6059
private static final Logger LOG = LoggerFactory.getLogger(GreyNoiseQuickIPDataAdapter.class);
6160
public static final String NAME = "GreyNoise";
62-
static final String GREYNOISE_IPQC_ENDPOINT = "https://api.greynoise.io/v2/noise/quick/";
61+
// v3 unified IP Lookup endpoint; the quick variant is selected with the "quick=true" query parameter.
62+
static final String GREYNOISE_IPQC_ENDPOINT = "https://api.greynoise.io/v3/ip/";
6363

6464
private final EncryptedValueService encryptedValueService;
6565
private final Config config;
6666
private final OkHttpClient okHttpClient;
6767
private final CustomizationConfig customizationConfig;
68+
private final ObjectMapper objectMapper;
6869

6970
private static final AtomicBoolean VALID_GREYNOISE_LICENSE = new AtomicBoolean(false);
7071

@@ -75,12 +76,14 @@ public GreyNoiseQuickIPDataAdapter(@Assisted("id") String id,
7576
MetricRegistry metricRegistry,
7677
EncryptedValueService encryptedValueService,
7778
OkHttpClient okHttpClient,
78-
CustomizationConfig customizationConfig) {
79+
CustomizationConfig customizationConfig,
80+
ObjectMapper objectMapper) {
7981
super(id, name, config, metricRegistry);
8082
this.config = (Config) config;
8183
this.encryptedValueService = encryptedValueService;
8284
this.okHttpClient = okHttpClient;
8385
this.customizationConfig = customizationConfig;
86+
this.objectMapper = objectMapper;
8487
}
8588

8689
@Override
@@ -135,10 +138,10 @@ protected LookupResult doGet(Object keyObject) {
135138
}
136139
}
137140
Request request = new Request.Builder()
138-
.url(GREYNOISE_IPQC_ENDPOINT + ip)
141+
.url(GREYNOISE_IPQC_ENDPOINT + ip + "?quick=true")
139142
.method("GET", null)
140143
.addHeader("Accept", "application/json")
141-
.addHeader("key", encryptedValueService.decrypt(config.apiToken()))
144+
.addHeader("key", Objects.requireNonNull(encryptedValueService.decrypt(config.apiToken())))
142145
.addHeader("User-Agent", customizationConfig.productName())
143146
.build();
144147
try (Response response = okHttpClient.newCall(request).execute()) {
@@ -150,18 +153,31 @@ protected LookupResult doGet(Object keyObject) {
150153
}
151154

152155
@VisibleForTesting
153-
static LookupResult parseResponse(Response response) {
154-
156+
LookupResult parseResponse(Response response) {
155157
if (response.isSuccessful()) {
156158
Map<Object, Object> map = Maps.newHashMap();
157159

158160
try {
159-
JSONObject obj = new JSONObject(response.body().string());
160-
map.put("ip", Objects.requireNonNull(obj).getFieldAsString("ip"));
161-
map.put("noise", Objects.requireNonNull(obj).getFieldAsBoolean("noise"));
162-
map.put("code", Objects.requireNonNull(obj).getFieldAsString("code"));
163-
map.put("riot", Objects.requireNonNull(obj).getFieldAsBoolean("riot"));
164-
} catch (JSONException | IOException e) {
161+
JsonNode root = objectMapper.readTree(response.body().string());
162+
if (root.hasNonNull("ip")) {
163+
map.put("ip", root.get("ip").asText());
164+
}
165+
166+
// v3 nests the scanner data; "found" is the v3 equivalent of the v2 top-level "noise" flag.
167+
JsonNode isi = root.path("internet_scanner_intelligence");
168+
map.put("noise", isi.path("found").asBoolean(false));
169+
if (isi.hasNonNull("classification")) {
170+
map.put("classification", isi.get("classification").asText());
171+
}
172+
173+
// v3 nests the RIOT data under business_service_intelligence; "found" replaces the v2 "riot" flag.
174+
JsonNode bsi = root.path("business_service_intelligence");
175+
map.put("riot", bsi.path("found").asBoolean(false));
176+
final String trustLevel = bsi.path("trust_level").asText("");
177+
if (!trustLevel.isEmpty()) {
178+
map.put("trust_level", trustLevel);
179+
}
180+
} catch (IOException e) {
165181
LOG.error("An error occurred while parsing Lookup result [{}]", e.toString());
166182
}
167183
return LookupResult.withoutTTL().multiValue(map).build();
@@ -174,7 +190,9 @@ static LookupResult parseResponse(Response response) {
174190
public void set(Object key, Object value) {
175191
}
176192

177-
// Check if provided API token has a valid non-community GreyNoise subscription.
193+
// Check if the provided API token is accepted by GreyNoise. The free/community tier has been retired, so any
194+
// authenticated request (HTTP 200) corresponds to a valid subscription, while an invalid or missing key returns
195+
// HTTP 401.
178196
private boolean isValidSubscription(String apiKey) {
179197
Request request = new Request.Builder()
180198
.url("https://api.greynoise.io/ping")
@@ -185,9 +203,7 @@ private boolean isValidSubscription(String apiKey) {
185203
.build();
186204

187205
try (Response response = okHttpClient.newCall(request).execute()) {
188-
JSONObject json = new JSONObject(response.body().string());
189-
return response.isSuccessful()
190-
&& json.hasField("offering") && !json.getFieldAsString("offering").equals("community");
206+
return response.isSuccessful();
191207
} catch (Exception e) {
192208
LOG.warn("An error occurred while retrieving subscription type.", e);
193209
return false;

0 commit comments

Comments
 (0)