Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -39476,7 +39476,6 @@
"xpack.securitySolution.entityAnalytics.riskDashboard.noEntity.riskLevelTitle": "Niveau de risque",
"xpack.securitySolution.entityAnalytics.riskDashboard.riskLevelTitle": "Score de risque de {riskEntity}",
"xpack.securitySolution.entityAnalytics.riskDashboard.viewAllLabel": "Afficher tout",
"xpack.securitySolution.entityAnalytics.riskEngine.missingClusterPrivilege": "Privilèges de cluster manquants : {privileges}.",
"xpack.securitySolution.entityAnalytics.riskEngine.missingIndexPrivilege": "Privilèges d'index manquants pour l'index \"{indexName}\" : {privileges}.",
"xpack.securitySolution.entityAnalytics.riskEngine.unauthorized": "L'utilisateur ne dispose pas des privilèges requis pour modifier le moteur de risque.",
"xpack.securitySolution.entityAnalytics.riskScore.chart.totalLabel": "Total",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39445,7 +39445,6 @@
"xpack.securitySolution.entityAnalytics.riskDashboard.noEntity.riskLevelTitle": "リスクレベル",
"xpack.securitySolution.entityAnalytics.riskDashboard.riskLevelTitle": "{riskEntity}リスクレベル",
"xpack.securitySolution.entityAnalytics.riskDashboard.viewAllLabel": "すべて表示",
"xpack.securitySolution.entityAnalytics.riskEngine.missingClusterPrivilege": "クラスター権限が不足しています:{privileges}。",
"xpack.securitySolution.entityAnalytics.riskEngine.missingIndexPrivilege": "インデックス\"{indexName}\"のインデックス権限が不足しています:{privileges}。",
"xpack.securitySolution.entityAnalytics.riskEngine.unauthorized": "ユーザーにはリスクエンジン権限がありません。",
"xpack.securitySolution.entityAnalytics.riskScore.chart.totalLabel": "合計",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39510,7 +39510,6 @@
"xpack.securitySolution.entityAnalytics.riskDashboard.noEntity.riskLevelTitle": "风险级别",
"xpack.securitySolution.entityAnalytics.riskDashboard.riskLevelTitle": "{riskEntity} 风险级别",
"xpack.securitySolution.entityAnalytics.riskDashboard.viewAllLabel": "查看全部",
"xpack.securitySolution.entityAnalytics.riskEngine.missingClusterPrivilege": "缺少集群权限:{privileges}。",
"xpack.securitySolution.entityAnalytics.riskEngine.missingIndexPrivilege": "缺少索引“{indexName}”的索引权限:{privileges}。",
"xpack.securitySolution.entityAnalytics.riskEngine.unauthorized": "用户缺少风险引擎权限。",
"xpack.securitySolution.entityAnalytics.riskScore.chart.totalLabel": "合计",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ export const RISK_ENGINE_CONFIGURE_SO_URL =
type ClusterPrivilege = 'manage_index_templates' | 'manage_transform' | 'manage_ingest_pipelines';
// These are the required privileges to install the risk engine - enabling and running require less privileges
// However, we check the full set for simplicity, since the UI does not distinguish between installing and enabling
export const RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES = [
export const TO_RUN_RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES = [
'manage_transform',
] as ClusterPrivilege[];

export const TO_ENABLE_RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES = [
'manage_index_templates',
'manage_transform',
'manage_ingest_pipelines',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ describe('getMissingRiskEnginePrivileges', () => {
const missingPrivileges = getMissingRiskEnginePrivileges(noClusterPrivileges);

expect(missingPrivileges).toEqual({
clusterPrivileges: ['manage_index_templates', 'manage_transform', 'manage_ingest_pipelines'],
clusterPrivileges: {
enable: ['manage_index_templates', 'manage_transform', 'manage_ingest_pipelines'],
run: ['manage_transform'],
},
indexPrivileges: [],
});
});
Expand All @@ -54,7 +57,7 @@ describe('getMissingRiskEnginePrivileges', () => {
const missingPrivileges = getMissingRiskEnginePrivileges(noIndexPrivileges);

expect(missingPrivileges).toEqual({
clusterPrivileges: [],
clusterPrivileges: { enable: [], run: [] },
indexPrivileges: [['risk-score.risk-score-*', ['read', 'write']]],
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import type { NonEmptyArray } from 'fp-ts/NonEmptyArray';
import type { EntityAnalyticsPrivileges } from '../../api/entity_analytics';
import type { RiskEngineIndexPrivilege } from './constants';
import {
RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES,
TO_ENABLE_RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES,
TO_RUN_RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES,
RISK_ENGINE_REQUIRED_ES_INDEX_PRIVILEGES,
} from './constants';

export type MissingClusterPrivileges = string[];
export interface MissingClusterPrivileges {
enable: string[];
run: string[];
}
export type MissingIndexPrivileges = Array<readonly [indexName: string, privileges: string[]]>;

export interface MissingPrivileges {
Expand Down Expand Up @@ -54,12 +58,20 @@ export const getMissingRiskEnginePrivileges = (
privileges.elasticsearch.index,
required
);
const missingClusterPrivileges = RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES.filter(
(privilege) => !privileges.elasticsearch.cluster?.[privilege]
);
const missingClusterPrivilegesToEnableEngine =
TO_ENABLE_RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES.filter(
(privilege) => !privileges.elasticsearch.cluster?.[privilege]
);
const missingClusterPrivilegesToRunEngine =
TO_RUN_RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES.filter(
(privilege) => !privileges.elasticsearch.cluster?.[privilege]
);

return {
indexPrivileges: missingIndexPrivileges,
clusterPrivileges: missingClusterPrivileges,
clusterPrivileges: {
enable: missingClusterPrivilegesToEnableEngine,
run: missingClusterPrivilegesToRunEngine,
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('userHasRiskEngineReadPermissions', () => {
isLoading: false,
hasAllRequiredPrivileges: false,
missingPrivileges: {
clusterPrivileges: [],
clusterPrivileges: { enable: ['N/A'], run: ['N/A'] },
indexPrivileges: [['risk-score.risk-score-*', ['read']]],
},
})
Expand All @@ -35,7 +35,7 @@ describe('userHasRiskEngineReadPermissions', () => {
isLoading: false,
hasAllRequiredPrivileges: false,
missingPrivileges: {
clusterPrivileges: [],
clusterPrivileges: { enable: ['N/A'], run: ['N/A'] },
indexPrivileges: [['other-index.other-index-*', ['read']]],
},
})
Expand All @@ -48,7 +48,7 @@ describe('userHasRiskEngineReadPermissions', () => {
isLoading: false,
hasAllRequiredPrivileges: false,
missingPrivileges: {
clusterPrivileges: [],
clusterPrivileges: { enable: ['N/A'], run: ['N/A'] },
indexPrivileges: [['risk-score.risk-score-*', ['write']]],
},
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const missingRiskEnginePrivileges: RiskEngineMissingPrivilegesResponse = {
isLoading: false,
hasAllRequiredPrivileges: false,
missingPrivileges: {
clusterPrivileges: [],
clusterPrivileges: { enable: [], run: [] },
indexPrivileges: [],
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,36 @@ export const MissingPrivilegesCallOutBody: React.FC<MissingPrivileges> = ({
</ul>
</>
) : null,
clusterPrivileges:
clusterPrivileges.length > 0 ? (
<>
<FormattedMessage
id="xpack.securitySolution.riskEngine.missingPrivilegesCallOut.messageBody.clusterPrivilegesTitle"
defaultMessage="Missing Elasticsearch cluster privileges:"
/>
<ul>
{clusterPrivileges.map((privilege) => (
<li key={privilege}>{privilege}</li>
))}
</ul>
</>
) : null,
clusterPrivileges: (
<>
{clusterPrivileges.enable.length > 0 && (
<>
<FormattedMessage
id="xpack.securitySolution.riskEngine.missingPrivilegesCallOut.messageBody.clusterPrivilegesEnableTitle"
defaultMessage="Missing Elasticsearch cluster privileges to enable Risk Score engine:"
/>
<ul>
{clusterPrivileges.enable.map((privilege) => (
<li key={privilege}>{privilege}</li>
))}
</ul>
</>
)}
{clusterPrivileges.run.length > 0 && (
<>
<FormattedMessage
id="xpack.securitySolution.riskEngine.missingPrivilegesCallOut.messageBody.clusterPrivilegesRunTitle"
defaultMessage="Missing Elasticsearch cluster privileges to run Risk Score engine:"
/>
<ul>
{clusterPrivileges.run.map((privilege) => (
<li key={privilege}>{privilege}</li>
))}
</ul>
</>
)}
</>
),
}}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@ export const useMissingRiskEnginePrivileges = (
};
}

if (privilegesResponse.has_all_required) {
return {
isLoading: false,
hasAllRequiredPrivileges: true,
};
}

const requiredIndexPrivileges: NonEmptyArray<RiskEngineIndexPrivilege> = readonly
? ['read']
: ['read', 'write'];
Expand All @@ -60,7 +53,7 @@ export const useMissingRiskEnginePrivileges = (
// Here we check if there are no missing privileges of the provided set of required privileges
if (
indexPrivileges.every(([_, missingPrivileges]) => missingPrivileges.length === 0) &&
(readonly || clusterPrivileges.length === 0) // cluster privileges check is required for write operations
(readonly || (clusterPrivileges.run.length === 0 && clusterPrivileges.enable.length === 0)) // cluster privileges check is required for write operations
) {
return {
isLoading: false,
Expand All @@ -73,7 +66,7 @@ export const useMissingRiskEnginePrivileges = (
hasAllRequiredPrivileges: false,
missingPrivileges: {
indexPrivileges,
clusterPrivileges: readonly ? [] : clusterPrivileges, // cluster privileges are not required for readonly
clusterPrivileges: readonly ? { enable: [], run: [] } : clusterPrivileges, // cluster privileges are not required for readonly
},
};
}, [isLoading, privilegesResponse, readonly]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,17 @@ export const EntityAnalyticsManagementPage = () => {
const [isLoading, setIsLoading] = useState(false);
const { mutate: scheduleNowRiskEngine } = useScheduleNowRiskEngineMutation();
const { addSuccess, addError } = useAppToasts();
const userCanRunEngine =
(!privileges.isLoading &&
(privileges.hasAllRequiredPrivileges ||
(!privileges.hasAllRequiredPrivileges &&
privileges.missingPrivileges?.clusterPrivileges?.run?.length === 0))) ||
false;

const handleRunEngineClick = async () => {
setIsLoading(true);
try {
scheduleNowRiskEngine();

if (!isLoading) {
addSuccess(i18n.RISK_SCORE_ENGINE_RUN_SUCCESS, { toastLifeTimeMs: 5000 });
}
Expand All @@ -71,6 +76,9 @@ export const EntityAnalyticsManagementPage = () => {

const isRunning = status === 'running' || (!!runAt && new Date(runAt) < new Date());

const runEngineBtnIsDisabled =
!currentRiskEngineStatus || isLoading || !userCanRunEngine || isRunning;

const formatTimeFromNow = (time: string | undefined): string => {
if (!time) {
return '';
Expand Down Expand Up @@ -103,6 +111,7 @@ export const EntityAnalyticsManagementPage = () => {
<EuiButton
size="s"
iconType="play"
disabled={runEngineBtnIsDisabled}
isLoading={isLoading}
onClick={handleRunEngineClick}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('_getMissingPrivilegesMessage', () => {
const result = _getMissingPrivilegesMessage(noClusterPrivileges);

expect(result).toMatchInlineSnapshot(
`"User is missing risk engine privileges. Missing cluster privileges: manage_index_templates, manage_transform, manage_ingest_pipelines."`
`"User is missing risk engine privileges. Missing cluster privileges to run the risk engine: manage_transform. Missing cluster privileges to enable the risk engine: manage_index_templates, manage_transform, manage_ingest_pipelines."`
);
});

Expand All @@ -59,7 +59,7 @@ describe('_getMissingPrivilegesMessage', () => {
const result = _getMissingPrivilegesMessage(noIndexPrivileges);

expect(result).toMatchInlineSnapshot(
`"User is missing risk engine privileges. Missing index privileges for index \\"risk-score.risk-score-*\\": read, write. "`
`"User is missing risk engine privileges. Missing index privileges for index \\"risk-score.risk-score-*\\": read, write. "`
);
});

Expand All @@ -86,7 +86,7 @@ describe('_getMissingPrivilegesMessage', () => {
const result = _getMissingPrivilegesMessage(noClusterOrIndexPrivileges);

expect(result).toMatchInlineSnapshot(
`"User is missing risk engine privileges. Missing index privileges for index \\"risk-score.risk-score-*\\": read, write. Missing cluster privileges: manage_index_templates, manage_transform, manage_ingest_pipelines."`
`"User is missing risk engine privileges. Missing index privileges for index \\"risk-score.risk-score-*\\": read, write. Missing cluster privileges to run the risk engine: manage_transform. Missing cluster privileges to enable the risk engine: manage_index_templates, manage_transform, manage_ingest_pipelines."`
);
});
});
Loading