Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions changelog/unreleased/pr-25754.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type = "f"
message = "Enforce clusterconfiguration:read permission on Cluster Configuration API endpoints"

pulls = ["25754"]
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.graylog2.cluster.Node;
import org.graylog2.cluster.NodeNotFoundException;
import org.graylog2.cluster.NodeService;
Expand All @@ -59,6 +60,7 @@
import org.graylog2.search.SearchQueryField;
import org.graylog2.search.SearchQueryParser;
import org.graylog2.shared.rest.resources.RestResource;
import org.graylog2.shared.security.RestPermissions;

import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -149,6 +151,7 @@ public NodeSummaryList nodes() {
@GET
@Path("/nodes/paginated")
@Timed
@RequiresPermissions(RestPermissions.CLUSTER_CONFIGURATION_READ)
@Operation(summary = "Get a paginated list of all server nodes in this cluster")
public PageListResponse<ServerNodeDto> nodes(@Parameter(name = "page") @QueryParam("page") @DefaultValue("1") int page,
@Parameter(name = "per_page") @QueryParam("per_page") @DefaultValue("50") int perPage,
Expand All @@ -172,6 +175,7 @@ public PageListResponse<ServerNodeDto> nodes(@Parameter(name = "page") @QueryPar
@GET
@Timed
@Path("/node")
@RequiresPermissions(RestPermissions.CLUSTER_CONFIGURATION_READ)
@Operation(summary = "Information about this node.",
description = "This is returning information of this node in context to its state in the cluster. " +
"Use the system API of the node itself to get system information.")
Expand All @@ -182,6 +186,7 @@ public NodeSummary node() throws NodeNotFoundException {
@GET
@Timed
@Path("/nodes/{nodeId}")
@RequiresPermissions(RestPermissions.CLUSTER_CONFIGURATION_READ)
@Operation(summary = "Information about a node.",
description = "This is returning information of a node in context to its state in the cluster. " +
"Use the system API of the node itself to get system information.")
Expand Down
55 changes: 35 additions & 20 deletions graylog2-web-interface/src/pages/ClusterConfigurationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,47 @@
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import React from 'react';
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

import { DocumentTitle, PageHeader } from 'components/common';
import ClusterConfigurationPageNavigation from 'components/cluster-configuration/ClusterConfigurationPageNavigation';
import HideOnCloud from 'util/conditional/HideOnCloud';
import IndexerClusterHealth from 'components/indexers/IndexerClusterHealth';
import ClusterConfigurationNodes from 'components/cluster-configuration/ClusterConfigurationNodes';
import useCurrentUser from 'hooks/useCurrentUser';
import { isPermitted } from 'util/PermissionsMixin';
import Routes from 'routing/Routes';

const ClusterConfigurationPage = () => (
<DocumentTitle title="Cluster Configuration">
<ClusterConfigurationPageNavigation />
<div>
<PageHeader title="Cluster Configuration">
<span>
This page provides a real-time overview of the nodes in your cluster. You can pause message processing at any
time. The process buffers will not accept any new messages until you resume it. If the message journal is
enabled for a node, which it is by default, incoming messages will be persisted to disk, even when processing
is disabled.
</span>
</PageHeader>
<HideOnCloud>
<IndexerClusterHealth minimal />
</HideOnCloud>
<ClusterConfigurationNodes />
</div>
</DocumentTitle>
);
const ClusterConfigurationPage = () => {
const currentUser = useCurrentUser();
const navigate = useNavigate();

useEffect(() => {
if (!isPermitted(currentUser.permissions, 'clusterconfiguration:read')) {
navigate(Routes.NOTFOUND);
}
}, [currentUser.permissions, navigate]);

return (
<DocumentTitle title="Cluster Configuration">
<ClusterConfigurationPageNavigation />
<div>
<PageHeader title="Cluster Configuration">
<span>
This page provides a real-time overview of the nodes in your cluster. You can pause message processing at any
time. The process buffers will not accept any new messages until you resume it. If the message journal is
enabled for a node, which it is by default, incoming messages will be persisted to disk, even when processing
is disabled.
</span>
</PageHeader>
<HideOnCloud>
<IndexerClusterHealth minimal />
</HideOnCloud>
<ClusterConfigurationNodes />
</div>
</DocumentTitle>
);
};

export default ClusterConfigurationPage;
Loading