mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* [Stack Monitoring] Verify remote cluster client role when CCS is enabled (#129546)
* Only show UI hint if CCS is enabled
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit f014ca46bc
)
Co-authored-by: Milton Hultgren <milton.hultgren@elastic.co>
This commit is contained in:
parent
47e112cf25
commit
7b2eae6ae5
5 changed files with 56 additions and 4 deletions
|
@ -13,6 +13,7 @@ export interface ExternalConfig {
|
|||
showCgroupMetricsLogstash: boolean;
|
||||
renderReactApp: boolean;
|
||||
staleStatusThresholdSeconds: number;
|
||||
isCcsEnabled: boolean;
|
||||
}
|
||||
|
||||
export const ExternalConfigContext = createContext({} as ExternalConfig);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiPanel, EuiCallOut, EuiButton } from '@elastic/eui';
|
||||
|
@ -14,8 +14,10 @@ import { Redirect } from 'react-router-dom';
|
|||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { ComponentProps } from '../../route_init';
|
||||
import { MonitoringStartPluginDependencies } from '../../../types';
|
||||
import { ExternalConfigContext } from '../../contexts/external_config_context';
|
||||
|
||||
export const AccessDeniedPage: React.FC<ComponentProps> = () => {
|
||||
const { isCcsEnabled } = useContext(ExternalConfigContext);
|
||||
const { services } = useKibana<MonitoringStartPluginDependencies>();
|
||||
const [hasAccess, setHasAccess] = useState<boolean>(false);
|
||||
|
||||
|
@ -62,6 +64,14 @@ export const AccessDeniedPage: React.FC<ComponentProps> = () => {
|
|||
the monitoring cluster."
|
||||
/>
|
||||
</p>
|
||||
{isCcsEnabled && (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.accessDenied.noRemoteClusterClientDescription"
|
||||
defaultMessage="Since Cross Cluster Search is enabled (`monitoring.ui.ccs.enabled` is set to `true`), make sure your cluster has the `remote_cluster_client` role on at least one node."
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
<p>
|
||||
<EuiButton href="../app/home">
|
||||
<FormattedMessage
|
||||
|
|
|
@ -149,6 +149,7 @@ export class MonitoringPlugin
|
|||
'staleStatusThresholdSeconds',
|
||||
monitoring.ui.kibana.reporting.stale_status_threshold_seconds,
|
||||
],
|
||||
['isCcsEnabled', monitoring.ui.ccs.enabled],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import { forbidden } from '@hapi/boom';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { getStatusCode } from './handle_error';
|
||||
import { ErrorTypes } from '../../types';
|
||||
import { NO_REMOTE_CLIENT_ROLE_ERROR } from '../../routes/api/v1/check_access/check_access';
|
||||
|
||||
export function isAuthError(err: ErrorTypes) {
|
||||
const statusCode = getStatusCode(err);
|
||||
|
@ -30,9 +31,15 @@ export function handleAuthError(err: ErrorTypes) {
|
|||
defaultMessage: 'Invalid authentication for monitoring cluster',
|
||||
});
|
||||
} else {
|
||||
message = i18n.translate('xpack.monitoring.errors.insufficientUserErrorMessage', {
|
||||
defaultMessage: 'Insufficient user permissions for monitoring data',
|
||||
});
|
||||
if (err.message === NO_REMOTE_CLIENT_ROLE_ERROR) {
|
||||
message = i18n.translate('xpack.monitoring.errors.noRemoteClientRoleErrorMessage', {
|
||||
defaultMessage: 'Cluster has no remote_cluster_client role',
|
||||
});
|
||||
} else {
|
||||
message = i18n.translate('xpack.monitoring.errors.insufficientUserErrorMessage', {
|
||||
defaultMessage: 'Insufficient user permissions for monitoring data',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return forbidden(message);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import Boom from '@hapi/boom';
|
||||
import { verifyMonitoringAuth } from '../../../../lib/elasticsearch/verify_monitoring_auth';
|
||||
import { handleError } from '../../../../lib/errors';
|
||||
import { LegacyRequest, MonitoringCore } from '../../../../types';
|
||||
|
@ -24,6 +25,11 @@ export function checkAccessRoute(server: MonitoringCore) {
|
|||
const response: { has_access?: boolean } = {};
|
||||
try {
|
||||
await verifyMonitoringAuth(req);
|
||||
|
||||
if (server.config.ui.ccs.enabled) {
|
||||
await verifyClusterHasRemoteClusterClientRole(req);
|
||||
}
|
||||
|
||||
response.has_access = true; // response data is ignored
|
||||
} catch (err) {
|
||||
throw handleError(err, req);
|
||||
|
@ -32,3 +38,30 @@ export function checkAccessRoute(server: MonitoringCore) {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
interface NodesResponse {
|
||||
nodes: {
|
||||
[uuid: string]: {
|
||||
roles: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export const NO_REMOTE_CLIENT_ROLE_ERROR = 'Cluster has no remote_cluster_client role';
|
||||
|
||||
async function verifyClusterHasRemoteClusterClientRole(req: LegacyRequest) {
|
||||
const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
|
||||
|
||||
const response: NodesResponse = await callWithRequest(req, 'transport.request', {
|
||||
method: 'GET',
|
||||
path: '/_nodes',
|
||||
});
|
||||
|
||||
for (const node of Object.values(response.nodes)) {
|
||||
if (node.roles.includes('remote_cluster_client')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw Boom.forbidden(NO_REMOTE_CLIENT_ROLE_ERROR);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue