[SecuritySolution][Detections] Fix "Closing a signal silently fails with reduced privileges" (#86908) (#87413)
## Summary This PR introduces the following changes. If the user has insufficient write privileges on the signals index: - we disable the status-changing actions on detection alerts ("Open alert", "Close Alert", "Mark in progress") in the context menu of an alert in alerts table - we make sure to show the corresponding callout that tells about read-only access to detection alerts - in the callout we provide links to docs for understanding why/how to fix Co-authored-by: Georgii Gorbachev <georgii.gorbachev@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
14fcfba0cb
commit
4867610afb
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FC, memo } from 'react';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import { ExternalLink } from './external_link';
|
||||
import { COMMON_ARIA_LABEL_ENDING } from './links_translations';
|
||||
|
||||
interface DocLinkProps {
|
||||
guidePath?: string;
|
||||
docPath: string;
|
||||
linkText: string;
|
||||
}
|
||||
|
||||
const DocLink: FC<DocLinkProps> = ({ guidePath = 'security', docPath, linkText }) => {
|
||||
const { services } = useKibana();
|
||||
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = services.docLinks;
|
||||
|
||||
const url = `${ELASTIC_WEBSITE_URL}guide/en/${guidePath}/${DOC_LINK_VERSION}/${docPath}`;
|
||||
const ariaLabel = `${linkText} - ${COMMON_ARIA_LABEL_ENDING}`;
|
||||
|
||||
return <ExternalLink url={url} text={linkText} ariaLabel={ariaLabel} />;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple text link to documentation.
|
||||
*/
|
||||
const DocLinkWrapper = memo(DocLink);
|
||||
|
||||
export { DocLinkWrapper as DocLink };
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FC } from 'react';
|
||||
import { EuiLink } from '@elastic/eui';
|
||||
|
||||
interface ExternalLinkProps {
|
||||
url: string;
|
||||
text: string;
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simplistic text link for opening external urls in a new browser tab.
|
||||
*/
|
||||
export const ExternalLink: FC<ExternalLinkProps> = ({ url, text, ariaLabel }) => {
|
||||
return (
|
||||
<EuiLink href={url} aria-label={ariaLabel} external target="_blank" rel="noopener">
|
||||
{text}
|
||||
</EuiLink>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export * from './links_components';
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { DocLink } from './doc_link';
|
||||
import * as i18n from './links_translations';
|
||||
|
||||
export const SecuritySolutionRequirementsLink = () => (
|
||||
<DocLink
|
||||
docPath={i18n.SOLUTION_REQUIREMENTS_LINK_PATH}
|
||||
linkText={i18n.SOLUTION_REQUIREMENTS_LINK_TEXT}
|
||||
/>
|
||||
);
|
||||
|
||||
export const DetectionsRequirementsLink = () => (
|
||||
<DocLink
|
||||
docPath={i18n.DETECTIONS_REQUIREMENTS_LINK_PATH}
|
||||
linkText={i18n.DETECTIONS_REQUIREMENTS_LINK_TEXT}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
/**
|
||||
* If a link's text is "Docs", its aria-label will be set to
|
||||
* "Docs - ${COMMON_ARIA_LABEL_ENDING}".
|
||||
*/
|
||||
export const COMMON_ARIA_LABEL_ENDING = i18n.translate(
|
||||
'xpack.securitySolution.documentationLinks.ariaLabelEnding',
|
||||
{
|
||||
defaultMessage: 'click to open documentation in a new tab',
|
||||
}
|
||||
);
|
||||
|
||||
export const SOLUTION_REQUIREMENTS_LINK_PATH = 'sec-requirements.html';
|
||||
export const SOLUTION_REQUIREMENTS_LINK_TEXT = i18n.translate(
|
||||
'xpack.securitySolution.documentationLinks.solutionRequirements.text',
|
||||
{
|
||||
defaultMessage: 'Elastic Security system requirements',
|
||||
}
|
||||
);
|
||||
|
||||
export const DETECTIONS_REQUIREMENTS_LINK_PATH = 'detections-permissions-section.html';
|
||||
export const DETECTIONS_REQUIREMENTS_LINK_TEXT = i18n.translate(
|
||||
'xpack.securitySolution.documentationLinks.detectionsRequirements.text',
|
||||
{
|
||||
defaultMessage: 'Detections prerequisites and requirements',
|
||||
}
|
||||
);
|
|
@ -98,7 +98,7 @@ const AlertContextMenuComponent: React.FC<AlertContextMenuProps> = ({
|
|||
setPopover(false);
|
||||
}, []);
|
||||
const [exceptionModalType, setOpenAddExceptionModal] = useState<ExceptionListType | null>(null);
|
||||
const [{ canUserCRUD, hasIndexWrite }] = useUserData();
|
||||
const [{ canUserCRUD, hasIndexWrite, hasIndexUpdateDelete }] = useUserData();
|
||||
|
||||
const isEndpointAlert = useMemo((): boolean => {
|
||||
if (ecsRowData == null) {
|
||||
|
@ -218,7 +218,7 @@ const AlertContextMenuComponent: React.FC<AlertContextMenuProps> = ({
|
|||
data-test-subj="open-alert-status"
|
||||
id={FILTER_OPEN}
|
||||
onClick={openAlertActionOnClick}
|
||||
disabled={!canUserCRUD || !hasIndexWrite}
|
||||
disabled={!canUserCRUD || !hasIndexUpdateDelete}
|
||||
>
|
||||
<EuiText size="m">{i18n.ACTION_OPEN_ALERT}</EuiText>
|
||||
</EuiContextMenuItem>
|
||||
|
@ -251,7 +251,7 @@ const AlertContextMenuComponent: React.FC<AlertContextMenuProps> = ({
|
|||
data-test-subj="close-alert-status"
|
||||
id={FILTER_CLOSED}
|
||||
onClick={closeAlertActionClick}
|
||||
disabled={!canUserCRUD || !hasIndexWrite}
|
||||
disabled={!canUserCRUD || !hasIndexUpdateDelete}
|
||||
>
|
||||
<EuiText size="m">{i18n.ACTION_CLOSE_ALERT}</EuiText>
|
||||
</EuiContextMenuItem>
|
||||
|
@ -284,7 +284,7 @@ const AlertContextMenuComponent: React.FC<AlertContextMenuProps> = ({
|
|||
data-test-subj="in-progress-alert-status"
|
||||
id={FILTER_IN_PROGRESS}
|
||||
onClick={inProgressAlertActionClick}
|
||||
disabled={!canUserCRUD || !hasIndexWrite}
|
||||
disabled={!canUserCRUD || !hasIndexUpdateDelete}
|
||||
>
|
||||
<EuiText size="m">{i18n.ACTION_IN_PROGRESS_ALERT}</EuiText>
|
||||
</EuiContextMenuItem>
|
||||
|
|
|
@ -14,16 +14,16 @@ const readOnlyAccessToAlertsMessage: CallOutMessage = {
|
|||
type: 'primary',
|
||||
id: 'read-only-access-to-alerts',
|
||||
title: i18n.READ_ONLY_ALERTS_CALLOUT_TITLE,
|
||||
description: <p>{i18n.READ_ONLY_ALERTS_CALLOUT_MSG}</p>,
|
||||
description: i18n.readOnlyAlertsCallOutBody(),
|
||||
};
|
||||
|
||||
const ReadOnlyAlertsCallOutComponent = () => {
|
||||
const [{ hasIndexWrite }] = useUserData();
|
||||
const [{ hasIndexUpdateDelete }] = useUserData();
|
||||
|
||||
return (
|
||||
<CallOutSwitcher
|
||||
namespace="detections"
|
||||
condition={hasIndexWrite != null && !hasIndexWrite}
|
||||
condition={hasIndexUpdateDelete != null && !hasIndexUpdateDelete}
|
||||
message={readOnlyAccessToAlertsMessage}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const READ_ONLY_ALERTS_CALLOUT_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.readOnlyAlertsCallOutTitle',
|
||||
{
|
||||
defaultMessage: 'You cannot change alert states',
|
||||
}
|
||||
);
|
||||
|
||||
export const READ_ONLY_ALERTS_CALLOUT_MSG = i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.readOnlyAlertsCallOutMsg',
|
||||
{
|
||||
defaultMessage:
|
||||
'You only have permissions to view alerts. If you need to update alert states (open or close alerts), contact your Kibana administrator.',
|
||||
}
|
||||
);
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import {
|
||||
SecuritySolutionRequirementsLink,
|
||||
DetectionsRequirementsLink,
|
||||
} from '../../../../common/components/links_to_docs';
|
||||
|
||||
export const READ_ONLY_ALERTS_CALLOUT_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.readOnlyAlertsCallOut.messageTitle',
|
||||
{
|
||||
defaultMessage: 'You cannot change alert states',
|
||||
}
|
||||
);
|
||||
|
||||
export const readOnlyAlertsCallOutBody = () => (
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.detectionEngine.readOnlyAlertsCallOut.messageBody.messageDetail"
|
||||
defaultMessage="{essence} Related documentation: {docs}"
|
||||
values={{
|
||||
essence: (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.detectionEngine.readOnlyAlertsCallOut.messageBody.essenceDescription"
|
||||
defaultMessage="You only have permissions to view alerts. If you need to update alert states (open or close alerts), contact your Kibana administrator."
|
||||
/>
|
||||
</p>
|
||||
),
|
||||
docs: (
|
||||
<ul>
|
||||
<li>
|
||||
<DetectionsRequirementsLink />
|
||||
</li>
|
||||
<li>
|
||||
<SecuritySolutionRequirementsLink />
|
||||
</li>
|
||||
</ul>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
|
@ -14,7 +14,7 @@ const readOnlyAccessToRulesMessage: CallOutMessage = {
|
|||
type: 'primary',
|
||||
id: 'read-only-access-to-rules',
|
||||
title: i18n.READ_ONLY_RULES_CALLOUT_TITLE,
|
||||
description: <p>{i18n.READ_ONLY_RULES_CALLOUT_MSG}</p>,
|
||||
description: i18n.readOnlyRulesCallOutBody(),
|
||||
};
|
||||
|
||||
const ReadOnlyRulesCallOutComponent = () => {
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const READ_ONLY_RULES_CALLOUT_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.readOnlyRulesCallOutTitle',
|
||||
{
|
||||
defaultMessage: 'Rule permissions required',
|
||||
}
|
||||
);
|
||||
|
||||
export const READ_ONLY_RULES_CALLOUT_MSG = i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.readOnlyRulesCallOutMsg',
|
||||
{
|
||||
defaultMessage:
|
||||
'You are currently missing the required permissions to create/edit detection engine rule. Please contact your administrator for further assistance.',
|
||||
}
|
||||
);
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import {
|
||||
SecuritySolutionRequirementsLink,
|
||||
DetectionsRequirementsLink,
|
||||
} from '../../../../common/components/links_to_docs';
|
||||
|
||||
export const READ_ONLY_RULES_CALLOUT_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.readOnlyRulesCallOut.messageTitle',
|
||||
{
|
||||
defaultMessage: 'Rule permissions required',
|
||||
}
|
||||
);
|
||||
|
||||
export const readOnlyRulesCallOutBody = () => (
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.detectionEngine.readOnlyRulesCallOut.messageBody.messageDetail"
|
||||
defaultMessage="{essence} Related documentation: {docs}"
|
||||
values={{
|
||||
essence: (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.detectionEngine.readOnlyRulesCallOut.messageBody.essenceDescription"
|
||||
defaultMessage="You are currently missing the required permissions to create/edit detection engine rule. Please contact your administrator for further assistance."
|
||||
/>
|
||||
</p>
|
||||
),
|
||||
docs: (
|
||||
<ul>
|
||||
<li>
|
||||
<DetectionsRequirementsLink />
|
||||
</li>
|
||||
<li>
|
||||
<SecuritySolutionRequirementsLink />
|
||||
</li>
|
||||
</ul>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
|
@ -38,6 +38,7 @@ describe('useUserInfo', () => {
|
|||
hasEncryptionKey: null,
|
||||
hasIndexManage: null,
|
||||
hasIndexWrite: null,
|
||||
hasIndexUpdateDelete: null,
|
||||
isAuthenticated: null,
|
||||
isSignalIndexExists: null,
|
||||
loading: true,
|
||||
|
|
|
@ -15,6 +15,7 @@ export interface State {
|
|||
canUserCRUD: boolean | null;
|
||||
hasIndexManage: boolean | null;
|
||||
hasIndexWrite: boolean | null;
|
||||
hasIndexUpdateDelete: boolean | null;
|
||||
isSignalIndexExists: boolean | null;
|
||||
isAuthenticated: boolean | null;
|
||||
hasEncryptionKey: boolean | null;
|
||||
|
@ -27,6 +28,7 @@ export const initialState: State = {
|
|||
canUserCRUD: null,
|
||||
hasIndexManage: null,
|
||||
hasIndexWrite: null,
|
||||
hasIndexUpdateDelete: null,
|
||||
isSignalIndexExists: null,
|
||||
isAuthenticated: null,
|
||||
hasEncryptionKey: null,
|
||||
|
@ -45,6 +47,10 @@ export type Action =
|
|||
type: 'updateHasIndexWrite';
|
||||
hasIndexWrite: boolean | null;
|
||||
}
|
||||
| {
|
||||
type: 'updateHasIndexUpdateDelete';
|
||||
hasIndexUpdateDelete: boolean | null;
|
||||
}
|
||||
| {
|
||||
type: 'updateIsSignalIndexExists';
|
||||
isSignalIndexExists: boolean | null;
|
||||
|
@ -90,6 +96,12 @@ export const userInfoReducer = (state: State, action: Action): State => {
|
|||
hasIndexWrite: action.hasIndexWrite,
|
||||
};
|
||||
}
|
||||
case 'updateHasIndexUpdateDelete': {
|
||||
return {
|
||||
...state,
|
||||
hasIndexUpdateDelete: action.hasIndexUpdateDelete,
|
||||
};
|
||||
}
|
||||
case 'updateIsSignalIndexExists': {
|
||||
return {
|
||||
...state,
|
||||
|
@ -151,6 +163,7 @@ export const useUserInfo = (): State => {
|
|||
canUserCRUD,
|
||||
hasIndexManage,
|
||||
hasIndexWrite,
|
||||
hasIndexUpdateDelete,
|
||||
isSignalIndexExists,
|
||||
isAuthenticated,
|
||||
hasEncryptionKey,
|
||||
|
@ -166,6 +179,7 @@ export const useUserInfo = (): State => {
|
|||
hasEncryptionKey: isApiEncryptionKey,
|
||||
hasIndexManage: hasApiIndexManage,
|
||||
hasIndexWrite: hasApiIndexWrite,
|
||||
hasIndexUpdateDelete: hasApiIndexUpdateDelete,
|
||||
} = usePrivilegeUser();
|
||||
const {
|
||||
loading: indexNameLoading,
|
||||
|
@ -197,6 +211,19 @@ export const useUserInfo = (): State => {
|
|||
}
|
||||
}, [dispatch, loading, hasIndexWrite, hasApiIndexWrite]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!loading &&
|
||||
hasIndexUpdateDelete !== hasApiIndexUpdateDelete &&
|
||||
hasApiIndexUpdateDelete != null
|
||||
) {
|
||||
dispatch({
|
||||
type: 'updateHasIndexUpdateDelete',
|
||||
hasIndexUpdateDelete: hasApiIndexUpdateDelete,
|
||||
});
|
||||
}
|
||||
}, [dispatch, loading, hasIndexUpdateDelete, hasApiIndexUpdateDelete]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!loading &&
|
||||
|
@ -272,6 +299,7 @@ export const useUserInfo = (): State => {
|
|||
canUserCRUD,
|
||||
hasIndexManage,
|
||||
hasIndexWrite,
|
||||
hasIndexUpdateDelete,
|
||||
signalIndexName,
|
||||
signalIndexMappingOutdated,
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ describe('usePrivilegeUser', () => {
|
|||
hasEncryptionKey: null,
|
||||
hasIndexManage: null,
|
||||
hasIndexWrite: null,
|
||||
hasIndexUpdateDelete: null,
|
||||
isAuthenticated: null,
|
||||
loading: true,
|
||||
});
|
||||
|
@ -38,6 +39,7 @@ describe('usePrivilegeUser', () => {
|
|||
hasEncryptionKey: true,
|
||||
hasIndexManage: true,
|
||||
hasIndexWrite: true,
|
||||
hasIndexUpdateDelete: true,
|
||||
isAuthenticated: true,
|
||||
loading: false,
|
||||
});
|
||||
|
@ -59,6 +61,7 @@ describe('usePrivilegeUser', () => {
|
|||
hasEncryptionKey: false,
|
||||
hasIndexManage: false,
|
||||
hasIndexWrite: false,
|
||||
hasIndexUpdateDelete: false,
|
||||
isAuthenticated: false,
|
||||
loading: false,
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@ export interface ReturnPrivilegeUser {
|
|||
hasEncryptionKey: boolean | null;
|
||||
hasIndexManage: boolean | null;
|
||||
hasIndexWrite: boolean | null;
|
||||
hasIndexUpdateDelete: boolean | null;
|
||||
}
|
||||
/**
|
||||
* Hook to get user privilege from
|
||||
|
@ -23,16 +24,12 @@ export interface ReturnPrivilegeUser {
|
|||
*/
|
||||
export const usePrivilegeUser = (): ReturnPrivilegeUser => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [privilegeUser, setPrivilegeUser] = useState<
|
||||
Pick<
|
||||
ReturnPrivilegeUser,
|
||||
'isAuthenticated' | 'hasEncryptionKey' | 'hasIndexManage' | 'hasIndexWrite'
|
||||
>
|
||||
>({
|
||||
const [privilegeUser, setPrivilegeUser] = useState<Omit<ReturnPrivilegeUser, 'loading'>>({
|
||||
isAuthenticated: null,
|
||||
hasEncryptionKey: null,
|
||||
hasIndexManage: null,
|
||||
hasIndexWrite: null,
|
||||
hasIndexUpdateDelete: null,
|
||||
});
|
||||
const [, dispatchToaster] = useStateToaster();
|
||||
|
||||
|
@ -59,6 +56,7 @@ export const usePrivilegeUser = (): ReturnPrivilegeUser => {
|
|||
privilege.index[indexName].create_doc ||
|
||||
privilege.index[indexName].index ||
|
||||
privilege.index[indexName].write,
|
||||
hasIndexUpdateDelete: privilege.index[indexName].write,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +67,7 @@ export const usePrivilegeUser = (): ReturnPrivilegeUser => {
|
|||
hasEncryptionKey: false,
|
||||
hasIndexManage: false,
|
||||
hasIndexWrite: false,
|
||||
hasIndexUpdateDelete: false,
|
||||
});
|
||||
errorToToaster({ title: i18n.PRIVILEGE_FETCH_FAILURE, error, dispatchToaster });
|
||||
}
|
||||
|
|
|
@ -16843,8 +16843,7 @@
|
|||
"xpack.securitySolution.detectionEngine.noApiIntegrationKeyCallOutMsg": "Kibanaを起動するごとに保存されたオブジェクトの新しい暗号化キーを作成します。永続キーがないと、Kibanaの再起動後にルールを削除または修正することができません。永続キーを設定するには、kibana.ymlファイルに32文字以上のテキスト値を付けてxpack.encryptedSavedObjects.encryptionKey設定を追加してください。",
|
||||
"xpack.securitySolution.detectionEngine.noApiIntegrationKeyCallOutTitle": "API統合キーが必要です",
|
||||
"xpack.securitySolution.detectionEngine.noIndexTitle": "検出エンジンを設定しましょう",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyAlertsCallOutMsg": "アラートを表示する権限のみが付与されています。アラート状態を更新(アラートを開く、アラートを閉じる)必要がある場合は、Kibana管理者に連絡してください。",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyAlertsCallOutTitle": "アラート状態を変更することはできません",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyAlertsCallOut.messageTitle": "アラート状態を変更することはできません",
|
||||
"xpack.securitySolution.detectionEngine.pageTitle": "検出エンジン",
|
||||
"xpack.securitySolution.detectionEngine.panelSubtitleShowing": "表示中",
|
||||
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphCountLabel": "カウント",
|
||||
|
@ -16859,8 +16858,7 @@
|
|||
"xpack.securitySolution.detectionEngine.queryPreview.queryPreviewGraphTitle": "{hits} {hits, plural, =1 {ヒット} other {ヒット}}",
|
||||
"xpack.securitySolution.detectionEngine.queryPreview.queryPreviewHelpText": "クエリ結果をプレビューするデータのタイムフレームを選択します",
|
||||
"xpack.securitySolution.detectionEngine.queryPreview.queryPreviewLabel": "クイッククエリプレビュー",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyRulesCallOutMsg": "現在、検出エンジンルールを作成/編集するための必要な権限がありません。サポートについては、管理者にお問い合わせください。",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyRulesCallOutTitle": "ルールアクセス権が必要です",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyRulesCallOut.messageTitle": "ルールアクセス権が必要です",
|
||||
"xpack.securitySolution.detectionEngine.rule.editRule.errorMsgDescription": "{countError, plural, one {このタブ} other {これらのタブ}}に無効な入力があります: {tabHasError}",
|
||||
"xpack.securitySolution.detectionEngine.ruleDescription.mlJobStartedDescription": "開始",
|
||||
"xpack.securitySolution.detectionEngine.ruleDescription.mlJobStoppedDescription": "停止",
|
||||
|
|
|
@ -16860,8 +16860,7 @@
|
|||
"xpack.securitySolution.detectionEngine.noApiIntegrationKeyCallOutMsg": "每次启动 Kibana,都会为已保存对象生成新的加密密钥。没有持久性密钥,在 Kibana 重新启动后,将无法删除或修改规则。要设置持久性密钥,请将文本值为 32 个或更多任意字符的 xpack.encryptedSavedObjects.encryptionKey 设置添加到 kibana.yml 文件。",
|
||||
"xpack.securitySolution.detectionEngine.noApiIntegrationKeyCallOutTitle": "需要 API 集成密钥",
|
||||
"xpack.securitySolution.detectionEngine.noIndexTitle": "让我们来设置您的检测引擎",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyAlertsCallOutMsg": "您仅有权查看告警。如果您需要更新告警状态(打开或关闭告警),请联系您的 Kibana 管理员。",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyAlertsCallOutTitle": "您无法更改告警状态",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyAlertsCallOut.messageTitle": "您无法更改告警状态",
|
||||
"xpack.securitySolution.detectionEngine.pageTitle": "检测引擎",
|
||||
"xpack.securitySolution.detectionEngine.panelSubtitleShowing": "正在显示",
|
||||
"xpack.securitySolution.detectionEngine.queryPreview.queryGraphCountLabel": "计数",
|
||||
|
@ -16876,8 +16875,7 @@
|
|||
"xpack.securitySolution.detectionEngine.queryPreview.queryPreviewGraphTitle": "{hits} 个{hits, plural, =1 {命中} other {命中}}",
|
||||
"xpack.securitySolution.detectionEngine.queryPreview.queryPreviewHelpText": "选择数据的时间范围以预览查询结果",
|
||||
"xpack.securitySolution.detectionEngine.queryPreview.queryPreviewLabel": "快速查询预览",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyRulesCallOutMsg": "您当前缺少所需的权限,无法创建/编辑检测引擎规则。有关进一步帮助,请联系您的管理员。",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyRulesCallOutTitle": "需要规则权限",
|
||||
"xpack.securitySolution.detectionEngine.readOnlyRulesCallOut.messageTitle": "需要规则权限",
|
||||
"xpack.securitySolution.detectionEngine.rule.editRule.errorMsgDescription": "您在{countError, plural, one {以下选项卡} other {以下选项卡}}中的输入无效:{tabHasError}",
|
||||
"xpack.securitySolution.detectionEngine.ruleDescription.mlJobStartedDescription": "已启动",
|
||||
"xpack.securitySolution.detectionEngine.ruleDescription.mlJobStoppedDescription": "已停止",
|
||||
|
|
Loading…
Reference in a new issue