From d664ffbd8f553ab3a43f13a36b3895854e071919 Mon Sep 17 00:00:00 2001 From: Antonio Date: Fri, 6 Oct 2023 16:40:33 +0200 Subject: [PATCH 01/15] [Cases] Fix null required custom field bug. (#168191) ## Summary Fixed the issue that allowed us to use the Cases API to create cases without required custom fields by passing the `null` value. --- .../cases/common/types/api/case/v1.test.ts | 34 +++++++++++++ .../plugins/cases/common/types/api/case/v1.ts | 8 ++-- .../cases/server/client/cases/create.test.ts | 46 ++++++++++++++++++ .../server/client/cases/validators.test.ts | 34 ++++++++++++- .../cases/server/client/cases/validators.ts | 14 ++++++ .../tests/common/cases/patch_cases.ts | 48 +++++++++++++++++++ .../tests/common/cases/post_case.ts | 41 ++++++++++++++-- 7 files changed, 215 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/cases/common/types/api/case/v1.test.ts b/x-pack/plugins/cases/common/types/api/case/v1.test.ts index ce27fe5070b2c4..e34d4be55ef0f6 100644 --- a/x-pack/plugins/cases/common/types/api/case/v1.test.ts +++ b/x-pack/plugins/cases/common/types/api/case/v1.test.ts @@ -320,6 +320,40 @@ describe('CasePostRequestRt', () => { `The length of the value is too long. The maximum length is ${MAX_CUSTOM_FIELD_TEXT_VALUE_LENGTH}.` ); }); + + it('throws an error when a text customFields is an empty array', () => { + expect( + PathReporter.report( + CasePostRequestRt.decode({ + ...defaultRequest, + customFields: [ + { + key: 'first_custom_field_key', + type: 'text', + value: [], + }, + ], + }) + ) + ).toContain('The length of the field value is too short. Array must be of length >= 1.'); + }); + + it('throws an error when a text customField is an array with an empty string', () => { + expect( + PathReporter.report( + CasePostRequestRt.decode({ + ...defaultRequest, + customFields: [ + { + key: 'first_custom_field_key', + type: 'text', + value: [''], + }, + ], + }) + ) + ).toContain('The value field cannot be an empty string.'); + }); }); describe('CasesFindRequestRt', () => { diff --git a/x-pack/plugins/cases/common/types/api/case/v1.ts b/x-pack/plugins/cases/common/types/api/case/v1.ts index f808080cc2f0de..35af579b4e99dd 100644 --- a/x-pack/plugins/cases/common/types/api/case/v1.ts +++ b/x-pack/plugins/cases/common/types/api/case/v1.ts @@ -44,21 +44,21 @@ import { CaseConnectorRt } from '../../domain/connector/v1'; import { CaseUserProfileRt, UserRt } from '../../domain/user/v1'; import { CasesStatusResponseRt } from '../stats/v1'; -const CaseCustomFieldWithValidationValueRt = limitedArraySchema({ +const CaseCustomFieldTextWithValidationValueRt = limitedArraySchema({ codec: limitedStringSchema({ fieldName: 'value', - min: 0, + min: 1, max: MAX_CUSTOM_FIELD_TEXT_VALUE_LENGTH, }), fieldName: 'value', - min: 0, + min: 1, max: MAX_CUSTOM_FIELD_TEXT_VALUE_ITEMS, }); const CaseCustomFieldTextWithValidationRt = rt.strict({ key: rt.string, type: CustomFieldTextTypeRt, - value: rt.union([CaseCustomFieldWithValidationValueRt, rt.null]), + value: rt.union([CaseCustomFieldTextWithValidationValueRt, rt.null]), }); const CustomFieldRt = rt.union([CaseCustomFieldTextWithValidationRt, CaseCustomFieldToggleRt]); diff --git a/x-pack/plugins/cases/server/client/cases/create.test.ts b/x-pack/plugins/cases/server/client/cases/create.test.ts index ae31b77058e1e3..4704f9002e33b3 100644 --- a/x-pack/plugins/cases/server/client/cases/create.test.ts +++ b/x-pack/plugins/cases/server/client/cases/create.test.ts @@ -570,6 +570,52 @@ describe('create', () => { ); }); + it('should throw an error when required customFields are null', async () => { + casesClient.configure.get = jest.fn().mockResolvedValue([ + { + owner: theCase.owner, + customFields: [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'foo', + required: true, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'foo', + required: true, + }, + ], + }, + ]); + + await expect( + create( + { + ...theCase, + customFields: [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + value: null, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + value: null, + }, + ], + }, + clientArgs, + casesClient + ) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Failed to create case: Error: Missing required custom fields: first_key,second_key"` + ); + }); + it('throws error when the customFields array is too long', async () => { await expect( create( diff --git a/x-pack/plugins/cases/server/client/cases/validators.test.ts b/x-pack/plugins/cases/server/client/cases/validators.test.ts index 6956440a256856..d9ba08ac63630c 100644 --- a/x-pack/plugins/cases/server/client/cases/validators.test.ts +++ b/x-pack/plugins/cases/server/client/cases/validators.test.ts @@ -305,7 +305,7 @@ describe('validators', () => { { key: 'second_key', type: CustomFieldTypes.TOGGLE as const, - value: null, + value: true, }, ]; expect(() => @@ -373,6 +373,38 @@ describe('validators', () => { ).toThrowErrorMatchingInlineSnapshot(`"Missing required custom fields: first_key"`); }); + it('throws if required custom fields have null value', () => { + const requestCustomFields: CaseCustomFields = [ + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + value: null, + }, + ]; + const customFieldsConfiguration: CustomFieldsConfiguration = [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'foo', + required: true, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'foo', + required: true, + }, + ]; + expect(() => + validateRequiredCustomFields({ + requestCustomFields, + customFieldsConfiguration, + }) + ).toThrowErrorMatchingInlineSnapshot( + `"Missing required custom fields: first_key,second_key"` + ); + }); + it('throws if configuration is missing and request has custom fields', () => { const requestCustomFields: CaseCustomFields = [ { diff --git a/x-pack/plugins/cases/server/client/cases/validators.ts b/x-pack/plugins/cases/server/client/cases/validators.ts index f33ac2ff4d0876..87e677dca457b2 100644 --- a/x-pack/plugins/cases/server/client/cases/validators.ts +++ b/x-pack/plugins/cases/server/client/cases/validators.ts @@ -107,12 +107,26 @@ export const validateRequiredCustomFields = ({ (customField) => customField.required ); + if (!requiredCustomFields.length) { + return; + } + const missingRequiredCustomFields = differenceWith( requiredCustomFields, requestCustomFields ?? [], (requiredVal, requestedVal) => requiredVal.key === requestedVal.key ).map((e) => e.key); + requiredCustomFields.forEach((requiredField) => { + const found = requestCustomFields?.find( + (requestField) => requestField.key === requiredField.key + ); + + if (found && found.value === null) { + missingRequiredCustomFields.push(found.key); + } + }); + if (missingRequiredCustomFields.length) { throw Boom.badRequest(`Missing required custom fields: ${missingRequiredCustomFields}`); } diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts index 576fc11cdf51b4..246b9c5c121318 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts @@ -1085,6 +1085,54 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('400s when trying to patch a case with a required custom field with null value', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'test_custom_field', + label: 'text', + type: CustomFieldTypes.TEXT, + required: true, + }, + ], + }, + }) + ); + + const postedCase = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'test_custom_field', + type: CustomFieldTypes.TEXT, + value: ['hello'], + }, + ], + }); + + await updateCase({ + supertest, + params: { + cases: [ + { + id: postedCase.id, + version: postedCase.version, + customFields: [ + { + key: 'test_custom_field', + type: CustomFieldTypes.TEXT, + value: null, + }, + ], + }, + ], + }, + expectedHttpCode: 400, + }); + }); it('400s when trying to patch a case with a custom field with the wrong type', async () => { await createConfiguration( supertest, diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts index 6d152008e90748..3272a778ee5f1f 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts @@ -482,14 +482,14 @@ export default ({ getService }: FtrProviderContext): void => { ); }); - it('400s when trying to create case with a required custom field', async () => { + it('400s when creating a case with a missing required custom field', async () => { await createConfiguration( supertest, getConfigurationRequest({ overrides: { customFields: [ { - key: 'test_custom_field', + key: 'text_custom_field', label: 'text', type: CustomFieldTypes.TEXT, required: false, @@ -509,9 +509,40 @@ export default ({ getService }: FtrProviderContext): void => { getPostCaseRequest({ customFields: [ { - key: 'test_custom_field', - type: CustomFieldTypes.TOGGLE, - value: true, + key: 'text_custom_field', + type: CustomFieldTypes.TEXT, + value: ['a'], + }, + ], + }), + 400 + ); + }); + + it('400s when trying to create case with a required custom field as null', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'text_custom_field', + label: 'text', + type: CustomFieldTypes.TEXT, + required: true, + }, + ], + }, + }) + ); + await createCase( + supertest, + getPostCaseRequest({ + customFields: [ + { + key: 'text_custom_field', + type: CustomFieldTypes.TEXT, + value: null, }, ], }), From b3b5d100dd834e24b1151e7631ff4a9eb95b903c Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Fri, 6 Oct 2023 08:49:06 -0600 Subject: [PATCH 02/15] [Security solution] Fix path for data generation script (#168047) --- x-pack/plugins/security_solution/scripts/mappings/README.md | 2 +- .../scripts/mappings/mappings_loader_script.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/scripts/mappings/README.md b/x-pack/plugins/security_solution/scripts/mappings/README.md index 3c209b237298ac..a612785fadf2ed 100644 --- a/x-pack/plugins/security_solution/scripts/mappings/README.md +++ b/x-pack/plugins/security_solution/scripts/mappings/README.md @@ -27,7 +27,7 @@ Available attributes: ### Load all generated buckets generated via previous command -> `node mappings_loader.js --mappings-dir='test_unmapped' --es-url=http://username:password@localhost:9200 --kibana-url=http://username:password@localhost:5601/app` +> `node mappings_loader.js --mappings-dir='test_unmapped' --es-url=http://elastic:changeme@localhost:9200 --kibana-url=http://elastic:changeme@localhost:5601/kbn/app` This script will go through each folder in the provided root folder (via `--mappings-dir`) and load each folder with mappings inside using `es_archiver` tool. diff --git a/x-pack/plugins/security_solution/scripts/mappings/mappings_loader_script.ts b/x-pack/plugins/security_solution/scripts/mappings/mappings_loader_script.ts index 9348bd1e173690..7997401f35e704 100644 --- a/x-pack/plugins/security_solution/scripts/mappings/mappings_loader_script.ts +++ b/x-pack/plugins/security_solution/scripts/mappings/mappings_loader_script.ts @@ -11,7 +11,7 @@ import path from 'path'; import yargs from 'yargs'; import { execSync } from 'child_process'; -const CONFIG_PATH = '../../../test/functional/config.base.js'; +const CONFIG_PATH = '../../../../../test/functional/config.base.js'; const loadAllIndices = (esUrl: string, kibanaUrl: string, mappingsDir: string) => { const exec = (cmd: string) => execSync(cmd, { stdio: 'inherit' }); @@ -40,7 +40,7 @@ const loadAllIndices = (esUrl: string, kibanaUrl: string, mappingsDir: string) = return; } exec( - `node ../../../scripts/es_archiver load ${fullPath} --config "${CONFIG_PATH}" --es-url=${esUrl} --kibana-url=${kibanaUrl}` + `node ../../../../../scripts/es_archiver load ${fullPath} --config "${CONFIG_PATH}" --es-url=${esUrl} --kibana-url=${kibanaUrl}` ); }); }); @@ -58,7 +58,7 @@ const main = () => { .option('kibana-url', { demandOption: false, type: 'string', - default: 'http://elastic:changeme@localhost:5601/app', + default: 'http://elastic:changeme@localhost:5601/kbn/app', description: 'The url for Kibana', }) .option('mappings-dir', { From ec313156f85b330be8dc9078b4d580cc8f836689 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:51:42 +0200 Subject: [PATCH 03/15] [Search] Add beats/logstash api key format (#168124) ## Summary This adds a beast/logstash format to the API key in getting started in Serverless Search. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../{public/application => common}/routes.ts | 4 ++-- .../components/api_key/api_key.tsx | 2 +- .../api_key/create_api_key_flyout.tsx | 2 +- .../application/components/api_key/types.ts | 1 + .../server/routes/api_key_routes.ts | 21 +++++++++++++++++++ 5 files changed, 26 insertions(+), 4 deletions(-) rename x-pack/plugins/serverless_search/{public/application => common}/routes.ts (75%) diff --git a/x-pack/plugins/serverless_search/public/application/routes.ts b/x-pack/plugins/serverless_search/common/routes.ts similarity index 75% rename from x-pack/plugins/serverless_search/public/application/routes.ts rename to x-pack/plugins/serverless_search/common/routes.ts index 2def1d368088c5..abaa3cac823145 100644 --- a/x-pack/plugins/serverless_search/public/application/routes.ts +++ b/x-pack/plugins/serverless_search/common/routes.ts @@ -8,6 +8,6 @@ export const MANAGEMENT_API_KEYS = '/app/management/security/api_keys'; // Server Routes -export const CREATE_API_KEY_PATH = '/internal/security/api_key'; +export const CREATE_API_KEY_PATH = '/internal/serverless_search/api_key'; export const FETCH_INDICES_PATH = '/internal/serverless_search/indices'; -export const CREATE_CONNECTOR_PATH = '/internal/connectors'; +export const CREATE_CONNECTORS_PATH = '/internal/connectors'; diff --git a/x-pack/plugins/serverless_search/public/application/components/api_key/api_key.tsx b/x-pack/plugins/serverless_search/public/application/components/api_key/api_key.tsx index 5e9758e134b2af..164bdacd5f985d 100644 --- a/x-pack/plugins/serverless_search/public/application/components/api_key/api_key.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/api_key/api_key.tsx @@ -25,7 +25,7 @@ import { ApiKey } from '@kbn/security-plugin/common'; import { useQuery } from '@tanstack/react-query'; import React, { useState } from 'react'; import { useKibanaServices } from '../../hooks/use_kibana'; -import { MANAGEMENT_API_KEYS } from '../../routes'; +import { MANAGEMENT_API_KEYS } from '../../../../common/routes'; import { CreateApiKeyFlyout } from './create_api_key_flyout'; import { CreateApiKeyResponse } from './types'; import './api_key.scss'; diff --git a/x-pack/plugins/serverless_search/public/application/components/api_key/create_api_key_flyout.tsx b/x-pack/plugins/serverless_search/public/application/components/api_key/create_api_key_flyout.tsx index d79b0974749153..7152795dde61d0 100644 --- a/x-pack/plugins/serverless_search/public/application/components/api_key/create_api_key_flyout.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/api_key/create_api_key_flyout.tsx @@ -40,7 +40,7 @@ import { } from '../../../../common/i18n_string'; import { CreateAPIKeyArgs } from '../../../../common/types'; import { useKibanaServices } from '../../hooks/use_kibana'; -import { CREATE_API_KEY_PATH } from '../../routes'; +import { CREATE_API_KEY_PATH } from '../../../../common/routes'; import { isApiError } from '../../../utils/api'; import { BasicSetupForm, DEFAULT_EXPIRES_VALUE } from './basic_setup_form'; import { MetadataForm } from './metadata_form'; diff --git a/x-pack/plugins/serverless_search/public/application/components/api_key/types.ts b/x-pack/plugins/serverless_search/public/application/components/api_key/types.ts index 6f98f68723edde..6cbffaf4f1a112 100644 --- a/x-pack/plugins/serverless_search/public/application/components/api_key/types.ts +++ b/x-pack/plugins/serverless_search/public/application/components/api_key/types.ts @@ -11,4 +11,5 @@ export interface CreateApiKeyResponse { expiration?: number; api_key: string; encoded?: string; + beats_logstash_format: string; } diff --git a/x-pack/plugins/serverless_search/server/routes/api_key_routes.ts b/x-pack/plugins/serverless_search/server/routes/api_key_routes.ts index a7fa0f0c2be396..9753420234208d 100644 --- a/x-pack/plugins/serverless_search/server/routes/api_key_routes.ts +++ b/x-pack/plugins/serverless_search/server/routes/api_key_routes.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { schema } from '@kbn/config-schema'; import { RouteDependencies } from '../plugin'; export const registerApiKeyRoutes = ({ logger, router, security }: RouteDependencies) => { @@ -27,4 +28,24 @@ export const registerApiKeyRoutes = ({ logger, router, security }: RouteDependen }); } ); + + router.post( + { + path: '/internal/serverless_search/api_key', + validate: { + body: schema.any(), + }, + }, + async (context, request, response) => { + const result = await security.authc.apiKeys.create(request, request.body); + if (result) { + const apiKey = { ...result, beats_logstash_format: `${result.id}:${result.api_key}` }; + return response.ok({ body: apiKey }); + } + return response.customError({ + statusCode: 502, + body: 'Could not retrieve current user, security plugin is not ready', + }); + } + ); }; From 098afd2f553e0b96100cdf0d6de7fd98a473c6e1 Mon Sep 17 00:00:00 2001 From: Davis McPhee Date: Fri, 6 Oct 2023 11:55:17 -0300 Subject: [PATCH 04/15] [Data View Field Editor] Fix `getErrorCodeFromErrorReason` check to work in both stateful and Serverless (#168125) ## Summary This PR fixes the `getErrorCodeFromErrorReason ` check to work in both stateful and Serverless. Oddly the `class_cast_exception: Cannot cast` issue mentioned in #165100 is intermittent. Sometimes the error reason is the same as stateful and only sometimes it incudes `class_cast_exception`, even though the failure is identical, but regardless this change fixes the issue. Flaky test runs: - x100: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3365 Fixes #165100. ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../public/lib/runtime_field_validation.ts | 2 +- .../common/data_view_field_editor/field_preview.ts | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/plugins/data_view_field_editor/public/lib/runtime_field_validation.ts b/src/plugins/data_view_field_editor/public/lib/runtime_field_validation.ts index 770fb548f12510..7ff5b80a7464fb 100644 --- a/src/plugins/data_view_field_editor/public/lib/runtime_field_validation.ts +++ b/src/plugins/data_view_field_editor/public/lib/runtime_field_validation.ts @@ -10,7 +10,7 @@ import { ScriptError } from '../components/preview/types'; import { RuntimeFieldPainlessError, PainlessErrorCode } from '../types'; export const getErrorCodeFromErrorReason = (reason: string = ''): PainlessErrorCode => { - if (reason.startsWith('Cannot cast from')) { + if (reason.includes('Cannot cast from')) { return 'CAST_ERROR'; } return 'UNKNOWN'; diff --git a/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts index 9580108506c0a5..9ed30298a9c3f6 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts @@ -48,8 +48,7 @@ export default function ({ getService }: FtrProviderContext) { }); }; - // Failing: See https://github.com/elastic/kibana/issues/165868 - describe.skip('Field preview', function () { + describe('Field preview', function () { before(async () => await createIndex()); after(async () => await deleteIndex()); @@ -149,10 +148,7 @@ export default function ({ getService }: FtrProviderContext) { // As ES does not return error codes we will add a test to make sure its error message string // does not change overtime as we rely on it to extract our own error code. // If this test fail we'll need to update the "getErrorCodeFromErrorReason()" handler - // TODO: `response.error?.caused_by?.reason` returns - // `class_cast_exception: Cannot cast from [int] to [java.lang.String].` - // in Serverless, which causes `getErrorCodeFromErrorReason` to fail - it.skip('should detect a script casting error', async () => { + it('should detect a script casting error', async () => { const { body: response } = await supertest .post(FIELD_PREVIEW_PATH) .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION) From 03148d7f79bd450d6a90fe2ce1d86a02c1e5adfa Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Fri, 6 Oct 2023 16:58:09 +0200 Subject: [PATCH 05/15] [Logs Onboarding] Fix casing on Elastic Agent text (#168197) In several places, "Elastic agent" instead of "Elastic Agent" was used. Before: Screenshot 2023-10-06 at 12 18 54 After: Screenshot 2023-10-06 at 12 25 32 --- .../public/components/app/home/index.tsx | 4 ++-- .../components/shared/install_elastic_agent_steps.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/observability_onboarding/public/components/app/home/index.tsx b/x-pack/plugins/observability_onboarding/public/components/app/home/index.tsx index 612a0c5710c135..90ed36a3d3fd41 100644 --- a/x-pack/plugins/observability_onboarding/public/components/app/home/index.tsx +++ b/x-pack/plugins/observability_onboarding/public/components/app/home/index.tsx @@ -258,7 +258,7 @@ export function Home() { 'xpack.observability_onboarding.card.k8s.description', { defaultMessage: - 'Collect logs and metrics from Kubernetes clusters with Elastic agent.', + 'Collect logs and metrics from Kubernetes clusters with Elastic Agent.', } )}

@@ -392,5 +392,5 @@ const getStartedLabel = i18n.translate( const elasticAgentLabel = i18n.translate( 'xpack.observability_onboarding.card.elasticAgent', - { defaultMessage: 'Elastic agent' } + { defaultMessage: 'Elastic Agent' } ); diff --git a/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx b/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx index aedd66f6d72454..a0847f34fc1a85 100644 --- a/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx +++ b/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx @@ -144,7 +144,7 @@ export function InstallElasticAgentSteps({ 'xpack.observability_onboarding.installElasticAgent.configStep.manual.description', { defaultMessage: - 'Add the following configuration to {configPath} on the host where you installed the Elastic agent.', + 'Add the following configuration to {configPath} on the host where you installed the Elastic Agent.', values: { configPath, }, @@ -157,7 +157,7 @@ export function InstallElasticAgentSteps({ isLoading={false} contentAriaLabel={i18n.translate( 'xpack.observability_onboarding.installElasticAgent.configStep.yamlCodeBlockdescription', - { defaultMessage: 'Elastic agent yaml configuration' } + { defaultMessage: 'Elastic Agent yaml configuration' } )} width="100%" height={300} @@ -326,7 +326,7 @@ export function InstallElasticAgentSteps({ 'data-test-subj': 'obltOnboardingConfigureElasticAgentStep', title: i18n.translate( 'xpack.observability_onboarding.installElasticAgent.configureStep.title', - { defaultMessage: 'Configure the Elastic agent' } + { defaultMessage: 'Configure the Elastic Agent' } ), status: disableSteps ? 'disabled' : configureAgentStatus, children: disableSteps ? <> : configureStep, From 14eaf25475614a6088f60cda5d9b9b5fa48357cb Mon Sep 17 00:00:00 2001 From: Michal Stanek <75310947+stanek-michal@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:33:13 +0200 Subject: [PATCH 06/15] Add Defend advanced option to exclude local connections from network events (#164235) ## Summary Add the following advanced policy option for Elastic Endpoint/Elastic Defend for all three OS (Linux, Mac, Windows): `network_events_exclude_local` with description: `Exclude local connections from network events. Default: false` ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../policy/models/advanced_policy_schema.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts index 46882ea876a9e4..51c080920c7adc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts @@ -189,6 +189,26 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ } ), }, + { + key: 'linux.advanced.network_events_exclude_local', + first_supported_version: '8.10.1', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.network_events_exclude_local', + { + defaultMessage: 'Exclude local connections from network events. Default: false.', + } + ), + }, + { + key: 'mac.advanced.network_events_exclude_local', + first_supported_version: '8.10.1', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.network_events_exclude_local', + { + defaultMessage: 'Exclude local connections from network events. Default: false.', + } + ), + }, { key: 'mac.advanced.agent.connection_delay', first_supported_version: '7.9', @@ -392,6 +412,16 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ } ), }, + { + key: 'windows.advanced.network_events_exclude_local', + first_supported_version: '8.10.1', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.network_events_exclude_local', + { + defaultMessage: 'Exclude local connections from network events. Default: false.', + } + ), + }, { key: 'windows.advanced.agent.connection_delay', first_supported_version: '7.9', From 34725165914bb1019c3094b709fa1589d28134f1 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Fri, 6 Oct 2023 16:37:49 +0100 Subject: [PATCH 07/15] skip flaky suite (#168222) --- .../alert_details_right_panel_overview_tab.cy.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_overview_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_overview_tab.cy.ts index ba0d5d984dfbe9..e93c74235f9b75 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_overview_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_overview_tab.cy.ts @@ -134,7 +134,8 @@ describe( }); }); - describe('visualizations section', () => { + // FLAKY: https://github.com/elastic/kibana/issues/168222 + describe.skip('visualizations section', () => { it('should display analyzer and session previews', () => { toggleOverviewTabAboutSection(); toggleOverviewTabVisualizationsSection(); From 08c3902c57ffad42a362c6f2d9a85b64abb8c6dc Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Fri, 6 Oct 2023 16:39:23 +0100 Subject: [PATCH 08/15] [APM] Add APM settings to allowlist for serverless (#167165) `uiSettings` need to be included to an allowlist to work on Serverless. This PR adds the APM settings to that list. ### Before https://github.com/elastic/kibana/assets/5831975/b176cd95-f31d-4403-bc76-190e722c85e6 ### After https://github.com/elastic/kibana/assets/5831975/d29dca3e-a182-47f2-96b9-6887593578e2 Closes https://github.com/elastic/kibana/issues/167119 --- .../kbn-management/settings/setting_ids/index.ts | 5 +++++ .../settings/observability_project/index.ts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/kbn-management/settings/setting_ids/index.ts b/packages/kbn-management/settings/setting_ids/index.ts index 1069050ccd3047..0613326d8f4282 100644 --- a/packages/kbn-management/settings/setting_ids/index.ts +++ b/packages/kbn-management/settings/setting_ids/index.ts @@ -128,6 +128,11 @@ export const OBSERVABILITY_ENABLE_INSPECT_ES_QUERIES_ID = 'observability:enableI export const OBSERVABILITY_MAX_SUGGESTIONS_ID = 'observability:maxSuggestions'; export const OBSERVABILITY_PROFILING_ELASTICSEARCH_PLUGIN_ID = 'observability:profilingElasticsearchPlugin'; +export const OBSERVABILITY_APM_ENABLE_SERVICE_METRICS_ID = 'observability:apmEnableServiceMetrics'; +export const OBSERVABILITY_APM_ENABLE_CONTINUOUS_ROLLUPS_ID = + 'observability:apmEnableContinuousRollups'; +export const OBSERVABILITY_APM_ENABLE_PROFILING_INTEGRATION_ID = + 'observability:apmEnableProfilingIntegration'; // Reporting settings export const XPACK_REPORTING_CUSTOM_PDF_LOGO_ID = 'xpackReporting:customPdfLogo'; diff --git a/packages/serverless/settings/observability_project/index.ts b/packages/serverless/settings/observability_project/index.ts index 7f76a35e0fcea7..a1ae020b8abe30 100644 --- a/packages/serverless/settings/observability_project/index.ts +++ b/packages/serverless/settings/observability_project/index.ts @@ -11,4 +11,20 @@ import * as settings from '@kbn/management-settings-ids'; export const OBSERVABILITY_PROJECT_SETTINGS = [ settings.ML_ANOMALY_DETECTION_RESULTS_ENABLE_TIME_DEFAULTS_ID, settings.ML_ANOMALY_DETECTION_RESULTS_TIME_DEFAULTS_ID, + settings.OBSERVABILITY_ENABLE_COMPARISON_BY_DEFAULT_ID, + settings.OBSERVABILITY_APM_DEFAULT_SERVICE_ENVIRONMENT_ID, + settings.OBSERVABILITY_APM_SERVICE_GROUP_MAX_NUMBER_OF_SERVCIE_ID, + settings.OBSERVABILITY_ENABLE_INSPECT_ES_QUERIES_ID, + settings.OBSERVABILITY_APM_LABS_BUTTON_ID, + settings.OBSERVABILITY_APM_AWS_LAMBDA_PRICE_FACTOR_ID, + settings.OBSERVABILITY_APM_AWS_LAMBDA_REQUEST_COST_PER_MILLION_ID, + settings.OBSERVABILITY_APM_ENABLE_SERVICE_METRICS_ID, + settings.OBSERVABILITY_APM_ENABLE_CONTINUOUS_ROLLUPS_ID, + settings.OBSERVABILITY_APM_AGENT_EXPLORER_VIEW_ID, + settings.OBSERVABILITY_APM_ENABLE_PROFILING_INTEGRATION_ID, + settings.OBSERVABILITY_APM_PROGRESSIVE_LOADING_ID, + settings.OBSERVABILITY_APM_SERVICE_INVENTORY_OPTIMIZED_SORTING_ID, + settings.OBSERVABILITY_APM_TRACE_EXPLORER_TAB_ID, + settings.OBSERVABILITY_ENABLE_AWS_LAMBDA_METRICS_ID, + settings.OBSERVABILITY_APM_ENABLE_CRITICAL_PATH_ID, ]; From dac2c7fc3579189719ab34b930c49939c9884895 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 6 Oct 2023 10:40:21 -0500 Subject: [PATCH 09/15] [build] Update ironbank base to UBI 9.2 (#168219) --- .../docker_generator/templates/ironbank/Dockerfile | 4 ++-- .../templates/ironbank/hardening_manifest.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile index a0d3a49a19a896..b68130f1d201c3 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile @@ -3,8 +3,8 @@ # Extract Kibana and make various file manipulations. ################################################################################ ARG BASE_REGISTRY=registry1.dso.mil -ARG BASE_IMAGE=redhat/ubi/ubi8 -ARG BASE_TAG=8.7 +ARG BASE_IMAGE=redhat/ubi/ubi9 +ARG BASE_TAG=9.2 FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as prep_files diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/hardening_manifest.yaml b/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/hardening_manifest.yaml index f0f4a01bef295c..558d0df40f3a9e 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/hardening_manifest.yaml +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/hardening_manifest.yaml @@ -13,8 +13,8 @@ tags: # Build args passed to Dockerfile ARGs args: - BASE_IMAGE: 'redhat/ubi/ubi8' - BASE_TAG: '8.6' + BASE_IMAGE: 'redhat/ubi/ubi9' + BASE_TAG: '9.2' # Docker image labels labels: From 06c7d8371232e681d91ac76d616d126502a06eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:42:51 +0100 Subject: [PATCH 10/15] [Profiling] Enable APM integration by default (#168181) Enabling APM-Profiling integration by default. --- x-pack/plugins/observability/server/ui_settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index 759c92e659070d..134ad77046dbcd 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -374,7 +374,7 @@ export const uiSettings: Record = { name: i18n.translate('xpack.observability.apmEnableProfilingIntegration', { defaultMessage: 'Enable Universal Profiling integration in APM', }), - value: false, + value: true, schema: schema.boolean(), requiresPageReload: false, }, From 8e44bcada4b9c2845ed73213ecf5ec46c160be70 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 6 Oct 2023 17:44:30 +0200 Subject: [PATCH 11/15] [ftr] skip tests that fail on MKI build #197 (#168225) ## Summary Skipping tests that fail on real serverless projects, tested in https://buildkite.com/elastic/appex-qa-serverless-kibana-ftr-tests/builds/197 with Kibana image made from commit 591efd4 --- .../test_suites/common/alerting/alert_documents.ts | 4 +++- .../api_integration/test_suites/common/alerting/rules.ts | 4 +++- .../test_suites/common/platform_security/api_keys.ts | 4 +++- .../functional/test_suites/observability/cases/configure.ts | 2 ++ .../observability_log_explorer/dataset_selector.ts | 4 +++- .../functional/test_suites/security/ftr/cases/view_case.ts | 4 +++- .../test_suites/security/ml/anomaly_detection_jobs_list.ts | 4 +++- .../test_suites/security/ml/data_frame_analytics_jobs_list.ts | 4 +++- 8 files changed, 23 insertions(+), 7 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts index a108ffa4f2d003..2248c0aaef3356 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts @@ -49,7 +49,9 @@ export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const objectRemover = new ObjectRemover(supertest); - describe('Alert documents', () => { + describe('Alert documents', function () { + // Timeout of 360000ms exceeded + this.tags(['skipOnMKI']); const RULE_TYPE_ID = '.es-query'; const ALERT_INDEX = '.alerts-stack.alerts-default'; let ruleId: string; diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts index 441dc06cab8297..0db0fad7dc1c48 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts @@ -35,7 +35,9 @@ export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const esDeleteAllIndices = getService('esDeleteAllIndices'); - describe('Alerting rules', () => { + describe('Alerting rules', function () { + // Timeout of 360000ms exceeded + this.tags(['skipOnMKI']); const RULE_TYPE_ID = '.es-query'; const ALERT_ACTION_INDEX = 'alert-action-es-query'; let actionId: string; diff --git a/x-pack/test_serverless/functional/test_suites/common/platform_security/api_keys.ts b/x-pack/test_serverless/functional/test_suites/common/platform_security/api_keys.ts index 610ab692a4b0f0..986e6d31c942e8 100644 --- a/x-pack/test_serverless/functional/test_suites/common/platform_security/api_keys.ts +++ b/x-pack/test_serverless/functional/test_suites/common/platform_security/api_keys.ts @@ -29,7 +29,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const es = getService('es'); const log = getService('log'); - describe('API keys', () => { + describe('API keys', function () { + // TimeoutError: Waiting for element to be located By(css selector, [data-test-subj="apiKeysCreatePromptButton"]) Wait timed out after 10028ms + this.tags(['failsOnMKI']); before(async () => { await pageObjects.svlCommonPage.login(); }); diff --git a/x-pack/test_serverless/functional/test_suites/observability/cases/configure.ts b/x-pack/test_serverless/functional/test_suites/observability/cases/configure.ts index 58b163584a8a22..9c46ad382c497a 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cases/configure.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/cases/configure.ts @@ -19,6 +19,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { const retry = getService('retry'); describe('Configure Case', function () { + // Error: timed out waiting for assertRadioGroupValue: Expected the radio group value to equal "close-by-pushing" + this.tags(['skipOnMKI']); before(async () => { await svlCommonPage.login(); diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/dataset_selector.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/dataset_selector.ts index ef51de3c4b693b..783997630bf417 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/dataset_selector.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/dataset_selector.ts @@ -34,7 +34,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const noIntegrationsTitle = 'No integrations found'; const noUncategorizedTitle = 'No data streams found'; - describe('Dataset Selector', () => { + describe('Dataset Selector', function () { + // TimeoutError: Waiting for element to be located By(css selector, [data-test-subj="datasetSelectorPopoverButton"]) + this.tags(['skipOnMKI']); before(async () => { await PageObjects.svlCommonPage.login(); await PageObjects.observabilityLogExplorer.removeInstalledPackages(); diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts index 5ad615a4f97a9f..244867a1a0a1b4 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cases/view_case.ts @@ -29,7 +29,9 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { const svlCommonNavigation = getPageObject('svlCommonNavigation'); const svlCommonPage = getPageObject('svlCommonPage'); - describe('Case View', () => { + describe('Case View', function () { + // security_exception: action [indices:data/write/delete/byquery] is unauthorized for user [elastic] with effective roles [superuser] on restricted indices [.kibana_alerting_cases], this action is granted by the index privileges [delete,write,all] + this.tags(['failsOnMKI']); before(async () => { await svlCommonPage.login(); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts b/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts index 2e60830d9f8602..b2257fc68e1357 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts @@ -12,7 +12,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['svlCommonPage']); const adJobId = 'fq_single_permission'; - describe('Anomaly detection jobs list', () => { + describe('Anomaly detection jobs list', function () { + // Error: Failed to delete all indices with pattern [.ml-*] + this.tags(['failsOnMKI']); before(async () => { await PageObjects.svlCommonPage.login(); diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts b/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts index 8cd6f2a5708e2a..f0dbed0ca9a7e7 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts @@ -13,7 +13,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['svlCommonPage']); const dfaJobId = 'iph_outlier_permission'; - describe('Data frame analytics jobs list', () => { + describe('Data frame analytics jobs list', function () { + // Error: Failed to delete all indices with pattern [.ml-*] + this.tags(['failsOnMKI']); before(async () => { await PageObjects.svlCommonPage.login(); From ea0a1a073e3d38fe8122854ca47b0698695bfa5d Mon Sep 17 00:00:00 2001 From: Robert Austin Date: Fri, 6 Oct 2023 11:58:31 -0400 Subject: [PATCH 12/15] Enable Security's Cypress tests on all PRs (#167516) ## Summary Security Solution writes e2e and other tests using Cypress. In the past, these tests, if they failed on a tracked branch, couldn't be easily skipped. They also weren't run in parallelized jobs. For primarily these reasons, they didn't run on most Kibana PRs. This PR moves these Cypress tests back to the main PR pipeline. Tests that fail on tracked branches create (or update) Github issues which can be used with the skip-test github workflow script to easily skip the failing tests. The pipeline steps are parallelized and run in under 40 minutes. ### Open Questions - [ ] Should this PR enable Serverless Security Defend Workflows Cypress Tests @patrykkopycinski ### Some buildkite pipelines that used to run only on Security PRs now run on all PRs: These steps run on all PRs with these changes - Security Solution Cypress Tests (general tests that haven't been organized into an area team) - Explore tests - Investigations Tests - Defend Workflows Tests - Defend Workflows Serverless - Threat Intel Tests - OS Query Tests - Security Solution Burning Changed Specs (these run only recently changed specs a few extra times) - Security Solution OpenAPI codegen - OSQuery burning - OSQuery Serverless
And these already run on all PRs - Serverless Security Cypress Tests - Serverless Explore tests - Serverless Investigations Tests
### Security Cypress tests run in the main `on merge` pipeline instead of the `on merge unsupported ftrs` pipeline: These steps run in the `on merge` pipeline with these changes: - Security Solution Cypress Tests - Explore Cypress Tests - Investigations Cypress Tests - Defend Workflows Cypress Tests - Defend Workflows Serverless Cypress Tests - Threat Intelligence Cypress Tests - Osquery Cypress Tests
and these already run on the `on merge` pipeline - Serverless Security Cypress Tests - Serverless Explore - Security Solution Cypress Tests - Serverless Investigations - Security Solution Cypress Tests
### Additional work to be done: We need to consolidate build steps, enhance test skipping to support Cypress-grep flags, avoid out-of-memory errors in cypress, enhance parallelization, improve Cypress reporting, and probably other things. These are tracked separately. Reach out to me if you need details. ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .buildkite/pipelines/on_merge.yml | 84 +++++++++++ .../pipelines/on_merge_unsupported_ftrs.yml | 60 -------- .buildkite/pipelines/pull_request/base.yml | 130 ++++++++++++++++++ .../pull_request/defend_workflows.yml | 26 ---- .../pull_request/osquery_cypress.yml | 40 ------ .../pull_request/security_solution.yml | 54 -------- .../pull_request/threat_intelligence.yml | 12 -- .../pipelines/pull_request/pipeline.ts | 42 ------ packages/kbn-openapi-generator/README.md | 21 +-- x-pack/plugins/threat_intelligence/README.md | 9 +- 10 files changed, 227 insertions(+), 251 deletions(-) delete mode 100644 .buildkite/pipelines/pull_request/defend_workflows.yml delete mode 100644 .buildkite/pipelines/pull_request/osquery_cypress.yml delete mode 100644 .buildkite/pipelines/pull_request/security_solution.yml delete mode 100644 .buildkite/pipelines/pull_request/threat_intelligence.yml diff --git a/.buildkite/pipelines/on_merge.yml b/.buildkite/pipelines/on_merge.yml index d567ac16af588e..5427a3081730de 100644 --- a/.buildkite/pipelines/on_merge.yml +++ b/.buildkite/pipelines/on_merge.yml @@ -115,6 +115,90 @@ steps: - exit_status: '*' limit: 1 + - command: .buildkite/scripts/steps/functional/security_solution.sh + label: 'Security Solution Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 16 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/security_solution_explore.sh + label: 'Explore - Security Solution Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 4 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/security_solution_investigations.sh + label: 'Investigations - Security Solution Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 8 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/defend_workflows.sh + label: 'Defend Workflows Cypress Tests' + agents: + queue: n2-4-virt + depends_on: build + timeout_in_minutes: 60 + parallelism: 6 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh + label: 'Defend Workflows Cypress Tests on Serverless' + agents: + queue: n2-4-virt + depends_on: build + timeout_in_minutes: 120 + parallelism: 2 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/threat_intelligence.sh + label: 'Threat Intelligence Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + parallelism: 2 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/osquery_cypress.sh + label: 'Osquery Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 50 + parallelism: 6 + retry: + automatic: + - exit_status: '*' + limit: 1 + - command: '.buildkite/scripts/steps/functional/on_merge_unsupported_ftrs.sh' label: Trigger unsupported ftr tests timeout_in_minutes: 10 diff --git a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml index ceef6e06ef96ff..6dee27db716594 100644 --- a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml +++ b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml @@ -49,66 +49,6 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution.sh - label: 'Security Solution Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - parallelism: 14 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_solution_investigations.sh - label: 'Investigations - Security Solution Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - parallelism: 6 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_solution_explore.sh - label: 'Explore - Security Solution Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 60 - parallelism: 2 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/defend_workflows.sh - label: 'Defend Workflows Cypress Tests' - agents: - queue: n2-4-virt - depends_on: build - timeout_in_minutes: 120 - parallelism: 6 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/osquery_cypress.sh - label: 'Osquery Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 50 - parallelism: 6 - retry: - automatic: - - exit_status: '*' - limit: 1 - - command: .buildkite/scripts/steps/functional/synthetics_plugin.sh label: 'Synthetics @elastic/synthetics Tests' agents: diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml index 04861de3dfac91..0a03db978fa21d 100644 --- a/.buildkite/pipelines/pull_request/base.yml +++ b/.buildkite/pipelines/pull_request/base.yml @@ -93,6 +93,136 @@ steps: - exit_status: '*' limit: 1 + - command: .buildkite/scripts/steps/functional/security_solution.sh + label: 'Security Solution Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 16 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/security_solution_explore.sh + label: 'Explore - Security Solution Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 4 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/security_solution_investigations.sh + label: 'Investigations - Security Solution Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 8 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/defend_workflows.sh + label: 'Defend Workflows Cypress Tests' + agents: + queue: n2-4-virt + depends_on: build + timeout_in_minutes: 60 + parallelism: 6 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh + label: 'Defend Workflows Cypress Tests on Serverless' + agents: + queue: n2-4-virt + depends_on: build + timeout_in_minutes: 120 + parallelism: 2 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/threat_intelligence.sh + label: 'Threat Intelligence Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + parallelism: 2 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/osquery_cypress.sh + label: 'Osquery Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 50 + parallelism: 6 + retry: + automatic: + - exit_status: '*' + limit: 1 + artifact_paths: + - 'target/kibana-osquery/**/*' + + - command: .buildkite/scripts/steps/functional/security_solution_burn.sh + label: 'Security Solution Cypress tests, burning changed specs' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 60 + parallelism: 1 + retry: + automatic: false + soft_fail: true + + - command: .buildkite/scripts/steps/code_generation/security_solution_codegen.sh + label: 'Security Solution OpenAPI codegen' + agents: + queue: n2-2-spot + timeout_in_minutes: 60 + parallelism: 1 + + - command: .buildkite/scripts/steps/functional/osquery_cypress_burn.sh + label: 'Osquery Cypress Tests, burning changed specs' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 50 + soft_fail: true + retry: + automatic: false + artifact_paths: + - 'target/kibana-osquery/**/*' + + - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh + label: 'Serverless Osquery Cypress Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 50 + parallelism: 6 + retry: + automatic: + - exit_status: '*' + limit: 1 + artifact_paths: + - 'target/kibana-osquery/**/*' + # status_exception: Native role management is not enabled in this Elasticsearch instance # - command: .buildkite/scripts/steps/functional/security_serverless_defend_workflows.sh # label: 'Serverless Security Defend Workflows Cypress Tests' diff --git a/.buildkite/pipelines/pull_request/defend_workflows.yml b/.buildkite/pipelines/pull_request/defend_workflows.yml deleted file mode 100644 index da79114cbebfbe..00000000000000 --- a/.buildkite/pipelines/pull_request/defend_workflows.yml +++ /dev/null @@ -1,26 +0,0 @@ -steps: - - command: .buildkite/scripts/steps/functional/defend_workflows.sh - label: 'Defend Workflows Cypress Tests' - agents: - queue: n2-4-virt - depends_on: build - timeout_in_minutes: 60 - parallelism: 6 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh - label: 'Defend Workflows Cypress Tests on Serverless' - agents: - queue: n2-4-virt - depends_on: build - timeout_in_minutes: 120 - parallelism: 2 - retry: - automatic: - - exit_status: '*' - limit: 1 - - diff --git a/.buildkite/pipelines/pull_request/osquery_cypress.yml b/.buildkite/pipelines/pull_request/osquery_cypress.yml deleted file mode 100644 index 07e26e8f1ff6b6..00000000000000 --- a/.buildkite/pipelines/pull_request/osquery_cypress.yml +++ /dev/null @@ -1,40 +0,0 @@ -steps: - - command: .buildkite/scripts/steps/functional/osquery_cypress.sh - label: 'Osquery Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 50 - parallelism: 6 - retry: - automatic: - - exit_status: '*' - limit: 1 - artifact_paths: - - "target/kibana-osquery/**/*" - - - command: .buildkite/scripts/steps/functional/osquery_cypress_burn.sh - label: 'Osquery Cypress Tests, burning changed specs' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 50 - soft_fail: true - retry: - automatic: false - artifact_paths: - - "target/kibana-osquery/**/*" - - - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh - label: 'Serverless Osquery Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 50 - parallelism: 6 - retry: - automatic: - - exit_status: '*' - limit: 1 - artifact_paths: - - "target/kibana-osquery/**/*" diff --git a/.buildkite/pipelines/pull_request/security_solution.yml b/.buildkite/pipelines/pull_request/security_solution.yml deleted file mode 100644 index c679d9397f7ad0..00000000000000 --- a/.buildkite/pipelines/pull_request/security_solution.yml +++ /dev/null @@ -1,54 +0,0 @@ -steps: - - command: .buildkite/scripts/steps/functional/security_solution.sh - label: 'Security Solution Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 60 - parallelism: 16 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_solution_explore.sh - label: 'Explore - Security Solution Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 60 - parallelism: 4 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_solution_investigations.sh - label: 'Investigations - Security Solution Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 60 - parallelism: 8 - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_solution_burn.sh - label: 'Security Solution Cypress tests, burning changed specs' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: false - soft_fail: true - - - command: .buildkite/scripts/steps/code_generation/security_solution_codegen.sh - label: 'Security Solution OpenAPI codegen' - agents: - queue: n2-2-spot - timeout_in_minutes: 60 - parallelism: 1 diff --git a/.buildkite/pipelines/pull_request/threat_intelligence.yml b/.buildkite/pipelines/pull_request/threat_intelligence.yml deleted file mode 100644 index b91be5faffdec0..00000000000000 --- a/.buildkite/pipelines/pull_request/threat_intelligence.yml +++ /dev/null @@ -1,12 +0,0 @@ -steps: - - command: .buildkite/scripts/steps/functional/threat_intelligence.sh - label: 'Threat Intelligence Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - parallelism: 2 - retry: - automatic: - - exit_status: '*' - limit: 1 diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index 80d1312af6e640..7a7fa0f59b9c70 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -59,38 +59,6 @@ const uploadPipeline = (pipelineContent: string | object) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/kbn_handlebars.yml')); } - if ( - (await doAnyChangesMatch([ - /^src\/plugins\/controls/, - /^packages\/kbn-securitysolution-.*/, - /^x-pack\/plugins\/lists/, - /^x-pack\/plugins\/security_solution/, - /^x-pack\/plugins\/timelines/, - /^x-pack\/plugins\/triggers_actions_ui\/public\/application\/sections\/action_connector_form/, - /^x-pack\/plugins\/triggers_actions_ui\/public\/application\/sections\/alerts_table/, - /^x-pack\/plugins\/triggers_actions_ui\/public\/application\/context\/actions_connectors_context\.tsx/, - /^x-pack\/test\/defend_workflows_cypress/, - /^x-pack\/test\/security_solution_cypress/, - /^fleet_packages\.json/, // It contains reference to prebuilt detection rules, we want to run security solution tests if it changes - ])) || - GITHUB_PR_LABELS.includes('ci:all-cypress-suites') - ) { - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/security_solution.yml')); - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/defend_workflows.yml')); - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/osquery_cypress.yml')); - } - - if ( - (await doAnyChangesMatch([ - /^x-pack\/plugins\/threat_intelligence/, - /^x-pack\/test\/threat_intelligence_cypress/, - /^x-pack\/plugins\/security_solution\/public\/threat_intelligence/, - ])) || - GITHUB_PR_LABELS.includes('ci:all-cypress-suites') - ) { - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/threat_intelligence.yml')); - } - if ( (await doAnyChangesMatch([ /^src\/plugins\/data/, @@ -140,16 +108,6 @@ const uploadPipeline = (pipelineContent: string | object) => { GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/fleet_cypress.yml')); - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/defend_workflows.yml')); - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/osquery_cypress.yml')); - } - - if ( - ((await doAnyChangesMatch([/^x-pack\/plugins\/osquery/, /^x-pack\/test\/osquery_cypress/])) || - GITHUB_PR_LABELS.includes('ci:all-cypress-suites')) && - !GITHUB_PR_LABELS.includes('ci:skip-cypress-osquery') - ) { - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/osquery_cypress.yml')); } if (await doAnyChangesMatch([/^x-pack\/plugins\/exploratory_view/])) { diff --git a/packages/kbn-openapi-generator/README.md b/packages/kbn-openapi-generator/README.md index fc75a76827934a..4a3ed910bca29d 100644 --- a/packages/kbn-openapi-generator/README.md +++ b/packages/kbn-openapi-generator/README.md @@ -94,6 +94,7 @@ export const InstallPrebuiltRulesResponse = z.object({ timelines_updated: z.number().int().min(0), }); ``` + ## Programmatic API Alternatively, you can use the code generator programmatically. You can create a script file and run it with `node` command. This could be useful if you want to set up code generation in your CI pipeline. Here's an example of such script: @@ -135,26 +136,26 @@ check_for_changed_files "yarn openapi:generate" true This scripts sets up the minimal environment required fro code generation and runs the code generation script. Then it checks if there are any changes and commits them if there are any using the `check_for_changed_files` function. -Then add the code generation script to your plugin build pipeline. Open your plugin build pipeline, for example `.buildkite/pipelines/pull_request/security_solution.yml`, and add the following command to the steps list adjusting the path to your code generation script: +Then add the code generation script to your plugin build pipeline. Open your plugin build pipeline, for example `.buildkite/pipelines/pull_request/base.yml`, and add the following command to the steps list adjusting the path to your code generation script: ```yaml - - command: .buildkite/scripts/steps/code_generation/security_solution_codegen.sh - label: 'Security Solution OpenAPI codegen' - agents: - queue: n2-2-spot - timeout_in_minutes: 60 - parallelism: 1 +- command: .buildkite/scripts/steps/code_generation/security_solution_codegen.sh + label: 'Security Solution OpenAPI codegen' + agents: + queue: n2-2-spot + timeout_in_minutes: 60 + parallelism: 1 ``` Now on every pull request the code generation script will run and commit the changes if there are any. ## OpenAPI Schema -The code generator supports the OpenAPI definitions described in the request, response, and component sections of the document. +The code generator supports the OpenAPI definitions described in the request, response, and component sections of the document. For every API operation (GET, POST, etc) it is required to specify the `operationId` field. This field is used to generate the name of the generated types. For example, if the `operationId` is `InstallPrebuiltRules` then the generated types will be named `InstallPrebuiltRulesResponse` and `InstallPrebuiltRulesRequest`. If the `operationId` is not specified then the code generation will throw an error. -The `x-codegen-enabled` field is used to enable or disable code generation for the operation. If it is not specified then code generation is disabled by default. This field could be also used to disable code generation of common components described in the `components` section of the OpenAPI specification. +The `x-codegen-enabled` field is used to enable or disable code generation for the operation. If it is not specified then code generation is disabled by default. This field could be also used to disable code generation of common components described in the `components` section of the OpenAPI specification. Keep in mind that disabling code generation for common components that are referenced by external OpenAPI specifications could lead to errors during code generation. @@ -198,4 +199,4 @@ paths: application/json: schema: $ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse' -``` +``` \ No newline at end of file diff --git a/x-pack/plugins/threat_intelligence/README.md b/x-pack/plugins/threat_intelligence/README.md index da2cf37fe749a8..b708a4fecaa3d0 100755 --- a/x-pack/plugins/threat_intelligence/README.md +++ b/x-pack/plugins/threat_intelligence/README.md @@ -84,14 +84,9 @@ You can use this approach to load separate data dumps for every test case, to co ### CI Execution -The entry point for PR testing is `.buildkite/pipelines/pull_request/threat_intelligence.yml` file, see that for details on +The entry point for PR testing is `.buildkite/pipelines/pull_request/base.yml` file, see that for details on how the test suite is executed & extra options regarding parallelism, retrying etc. -E2E tests for this plugin will only be executed if any of the files changed within the PR matches dependency list here: -`.buildkite/scripts/pipelines/pull_request/pipeline.ts` - -It is also possible to run all tests by attaching a PR flag: `ci:all-cypress-suites`. - ## FAQ ### How is the Threat Intelligence code loaded in Kibana? @@ -110,4 +105,4 @@ See [CONTRIBUTING.md](https://github.com/elastic/kibana/blob/main/x-pack/plugins ## Issues -Please report any issues in [this GitHub project](https://github.com/orgs/elastic/projects/758/). +Please report any issues in [this GitHub project](https://github.com/orgs/elastic/projects/758/). \ No newline at end of file From e49628acabcb8c566f9d30a72b88129151f829ee Mon Sep 17 00:00:00 2001 From: Umberto Pepato Date: Fri, 6 Oct 2023 18:01:18 +0200 Subject: [PATCH 13/15] [RAM] Enable read-only users to access rules (#167003) Closes #166613 ## Summary Enables users with read privilege on `Stack rules` to see the rules table and the rule detail page without editing capabilities. Before: ![image](https://github.com/elastic/kibana/assets/18363145/a377819f-b140-41a4-aad9-9f5a5d779d63) After: ![image](https://github.com/elastic/kibana/assets/18363145/0c1bbf08-0f7b-4778-ae3e-062b0bd49c8f) In case of empty rules lists, the prompt "Create your first rule" was shown, even to users without create permissions: ![image](https://github.com/elastic/kibana/assets/18363145/3beaadb5-7b54-473e-9daa-e96c79e5a9f4) To avoid confusion, read-only users now see the empty table instead: ![image](https://github.com/elastic/kibana/assets/18363145/f35d212a-bc3e-4ee6-a3af-605966efced9) In the rule detail page, users without access to `Actions and Connectors` now see a missing privileges message under `Actions` in the details panel instead of `No actions` and a `Forbidden` error toast. ![image](https://github.com/elastic/kibana/assets/18363145/7d3edeae-3cd0-44c5-be2b-57ba4b54f69e) Finally, the original missing authorization prompt now shows "read" instead of "create": ![image](https://github.com/elastic/kibana/assets/18363145/f88b492d-3b20-41ac-a7c7-3cdd7f971ee5) ## To test - Create an Elasticsearch query rule - Create a Role with read privilege granted in `Stack rules` (under Kibana > Management) and assign it to a user - Create a test user with the created role - Log in as the test user - Navigate to Stack Management > Rules - Check that the rules table is visible, with create and update actions disabled ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) --------- Co-authored-by: Xavier Mouligneau --- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../prompts/no_permission_prompt.tsx | 4 +- .../hooks/use_load_rule_types_query.ts | 4 ++ .../hooks/use_rules_list_ui_state.ts | 7 +++- .../components/rule_definition.test.tsx | 1 + .../components/rule_definition.tsx | 27 +++++++++--- .../rules_list/components/rules_list.tsx | 2 + .../apps/observability/pages/rules_page.ts | 42 +++++++++++++++++-- 10 files changed, 74 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index c1f3af869cb78e..7dcddfb492d0dc 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -38306,7 +38306,6 @@ "xpack.triggersActionsUI.sections.rulesList.monthsLabel": "mois", "xpack.triggersActionsUI.sections.rulesList.multipleTitle": "règles", "xpack.triggersActionsUI.sections.rulesList.noPermissionToCreateDescription": "Contactez votre administrateur système.", - "xpack.triggersActionsUI.sections.rulesList.noPermissionToCreateTitle": "Aucune autorisation pour créer des règles", "xpack.triggersActionsUI.sections.rulesList.previousSnooze": "Précédent", "xpack.triggersActionsUI.sections.rulesList.refreshRulesButtonLabel": "Actualiser", "xpack.triggersActionsUI.sections.rulesList.remainingSnoozeIndefinite": "Indéfiniment", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 18492c43f42164..fcdea36b116786 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -38297,7 +38297,6 @@ "xpack.triggersActionsUI.sections.rulesList.monthsLabel": "月", "xpack.triggersActionsUI.sections.rulesList.multipleTitle": "ルール", "xpack.triggersActionsUI.sections.rulesList.noPermissionToCreateDescription": "システム管理者にお問い合わせください。", - "xpack.triggersActionsUI.sections.rulesList.noPermissionToCreateTitle": "ルールを作成する権限がありません", "xpack.triggersActionsUI.sections.rulesList.previousSnooze": "前へ", "xpack.triggersActionsUI.sections.rulesList.refreshRulesButtonLabel": "更新", "xpack.triggersActionsUI.sections.rulesList.remainingSnoozeIndefinite": "永久", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 296b107b99e5c8..a8f2091c05fde2 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -38291,7 +38291,6 @@ "xpack.triggersActionsUI.sections.rulesList.monthsLabel": "个月", "xpack.triggersActionsUI.sections.rulesList.multipleTitle": "规则", "xpack.triggersActionsUI.sections.rulesList.noPermissionToCreateDescription": "请联系您的系统管理员。", - "xpack.triggersActionsUI.sections.rulesList.noPermissionToCreateTitle": "没有创建规则的权限", "xpack.triggersActionsUI.sections.rulesList.previousSnooze": "上一步", "xpack.triggersActionsUI.sections.rulesList.refreshRulesButtonLabel": "刷新", "xpack.triggersActionsUI.sections.rulesList.remainingSnoozeIndefinite": "无限期", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/no_permission_prompt.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/no_permission_prompt.tsx index 9063617e90f69a..49c277adbf08c7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/no_permission_prompt.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/no_permission_prompt.tsx @@ -16,8 +16,8 @@ export const NoPermissionPrompt = () => ( title={

} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts index d9b1f6080c18f8..4892341e573856 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts @@ -64,6 +64,9 @@ export const useLoadRuleTypesQuery = (props: UseLoadRuleTypesQueryProps) => { const authorizedToCreateAnyRules = authorizedRuleTypes.some( (ruleType) => ruleType.authorizedConsumers[ALERTS_FEATURE_ID]?.all ); + const authorizedToReadAnyRules = + authorizedToCreateAnyRules || + authorizedRuleTypes.some((ruleType) => ruleType.authorizedConsumers[ALERTS_FEATURE_ID]?.read); return { ruleTypesState: { @@ -73,6 +76,7 @@ export const useLoadRuleTypesQuery = (props: UseLoadRuleTypesQueryProps) => { }, hasAnyAuthorizedRuleType, authorizedRuleTypes, + authorizedToReadAnyRules, authorizedToCreateAnyRules, isSuccess, }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rules_list_ui_state.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rules_list_ui_state.ts index 95ad83ba1f1cb2..0f1c86240a2481 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rules_list_ui_state.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rules_list_ui_state.ts @@ -9,6 +9,7 @@ import { isEmpty } from 'lodash'; import { RulesListFilters } from '../../types'; interface UseUiProps { + authorizedToReadAnyRules: boolean; authorizedToCreateAnyRules: boolean; filters: RulesListFilters; hasDefaultRuleTypesFiltersOn: boolean; @@ -37,6 +38,7 @@ const getFilterApplied = ({ hasEmptyTypesFilter, filters }: GetFilterAppliedProp }; export const useRulesListUiState = ({ + authorizedToReadAnyRules, authorizedToCreateAnyRules, filters, hasDefaultRuleTypesFiltersOn, @@ -56,8 +58,9 @@ export const useRulesListUiState = ({ const isInitialLoading = isInitialLoadingRuleTypes || isInitialLoadingRules; const isLoading = isLoadingRuleTypes || isLoadingRules; - const showNoAuthPrompt = !isInitialLoadingRuleTypes && !authorizedToCreateAnyRules; - const showCreateFirstRulePrompt = !isLoading && !hasData && !isFilterApplied; + const showNoAuthPrompt = !isInitialLoadingRuleTypes && !authorizedToReadAnyRules; + const showCreateFirstRulePrompt = + !isLoading && !hasData && !isFilterApplied && authorizedToCreateAnyRules; const showSpinner = isInitialLoading && (isLoadingRuleTypes || (!showNoAuthPrompt && isLoadingRules)); const showRulesList = !showSpinner && !showCreateFirstRulePrompt && !showNoAuthPrompt; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.test.tsx index 148d0994fc4977..842822f98c43f0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.test.tsx @@ -23,6 +23,7 @@ jest.mock('./rule_actions', () => ({ jest.mock('../../../lib/capabilities', () => ({ hasAllPrivilege: jest.fn(() => true), hasSaveRulesCapability: jest.fn(() => true), + hasShowActionsCapability: jest.fn(() => true), hasExecuteActionsCapability: jest.fn(() => true), hasManageApiKeysCapability: jest.fn(() => true), })); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx index 6c7f133da753fa..721118b1d6f0e0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx @@ -21,7 +21,11 @@ import { formatDuration } from '@kbn/alerting-plugin/common'; import { RuleDefinitionProps } from '../../../../types'; import { RuleType, useLoadRuleTypes } from '../../../..'; import { useKibana } from '../../../../common/lib/kibana'; -import { hasAllPrivilege, hasExecuteActionsCapability } from '../../../lib/capabilities'; +import { + hasAllPrivilege, + hasExecuteActionsCapability, + hasShowActionsCapability, +} from '../../../lib/capabilities'; import { RuleActions } from './rule_actions'; import { RuleEdit } from '../../rule_form'; @@ -60,6 +64,7 @@ export const RuleDefinition: React.FunctionComponent = ({ values: { numberOfConditions }, }); }; + const canReadActions = hasShowActionsCapability(capabilities); const canExecuteActions = hasExecuteActionsCapability(capabilities); const canSaveRule = rule && @@ -209,11 +214,21 @@ export const RuleDefinition: React.FunctionComponent = ({ })} - + {canReadActions ? ( + + ) : ( + + + {i18n.translate('xpack.triggersActionsUI.ruleDetails.cannotReadActions', { + defaultMessage: 'Connector feature privileges are required to view actions', + })} + + + )} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index 83285163aeee3c..9949b515544923 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -243,6 +243,7 @@ export const RulesList = ({ ruleTypesState, hasAnyAuthorizedRuleType, authorizedRuleTypes, + authorizedToReadAnyRules, authorizedToCreateAnyRules, isSuccess: isLoadRuleTypesSuccess, } = useLoadRuleTypesQuery({ filteredRuleTypes }); @@ -285,6 +286,7 @@ export const RulesList = ({ }); const { showSpinner, showRulesList, showNoAuthPrompt, showCreateFirstRulePrompt } = useUiState({ + authorizedToReadAnyRules, authorizedToCreateAnyRules, filters, hasDefaultRuleTypesFiltersOn, diff --git a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts index e912a52d36a180..e9b87e203fad8a 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts @@ -297,9 +297,42 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { 'Create rule button', async () => await testSubjects.exists('createRuleButton') ); + await retry.waitFor( + 'Create rule button is enabled', + async () => await testSubjects.isEnabled('createRuleButton') + ); }); it(`shows the no permission prompt when the user has no permissions`, async () => { + // We kept this test to make sure that the stack management rule page + // is showing the right prompt corresponding to the right privileges. + // Knowing that o11y alert page won't come up if you do not have any + // kind of privileges to o11y + await observability.users.setTestUserRole({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + base: [], + feature: { + discover: ['read'], + }, + spaces: ['*'], + }, + ], + }); + await observability.alerts.common.navigateToRulesPage(); + await retry.waitFor( + 'No permissions prompt', + async () => await testSubjects.exists('noPermissionPrompt') + ); + await observability.users.restoreDefaultTestUserRole(); + }); + + it(`shows the rules list in read-only mode when the user only has read permissions`, async () => { await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ logs: ['read'], @@ -307,10 +340,13 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { ); await observability.alerts.common.navigateToRulesPage(); await retry.waitFor( - 'No permissions prompt', - async () => await testSubjects.exists('noPermissionPrompt') + 'Read-only rules list is visible', + async () => await testSubjects.exists('rulesList') + ); + await retry.waitFor( + 'Create rule button is disabled', + async () => !(await testSubjects.isEnabled('createRuleButton')) ); - await observability.users.restoreDefaultTestUserRole(); }); }); From 653cfb2e9bdc60fd633dfffbd1446b83e67fbfba Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 6 Oct 2023 12:23:41 -0400 Subject: [PATCH 14/15] skip failing test suite (#167076) --- x-pack/test/profiling_api_integration/tests/has_setup.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/profiling_api_integration/tests/has_setup.spec.ts b/x-pack/test/profiling_api_integration/tests/has_setup.spec.ts index 1c415f2240361d..11a5a877d798c7 100644 --- a/x-pack/test/profiling_api_integration/tests/has_setup.spec.ts +++ b/x-pack/test/profiling_api_integration/tests/has_setup.spec.ts @@ -24,7 +24,8 @@ export default function featureControlsTests({ getService }: FtrProviderContext) const es = getService('es'); registry.when('Profiling status check', { config: 'cloud' }, () => { - describe('Profiling is not set up and no data is loaded', () => { + // Failing: See https://github.com/elastic/kibana/issues/167076 + describe.skip('Profiling is not set up and no data is loaded', () => { before(async () => { await cleanUpProfilingData({ es, logger, bettertest }); }); From 0a2148f854b159240b0c1c72abc5a0740f5ee8aa Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Fri, 6 Oct 2023 18:30:05 +0200 Subject: [PATCH 15/15] Fix KibanaPageTemplate.BottomBar in serverless (#168235) ## Summary The latest changes applied [here ](https://github.com/elastic/kibana/pull/166840) caused the `KibanaPageTemplate.BottomBar` to not work properly: ![KibanaPageTemplate.BottomBar](https://github.com/elastic/kibana/assets/17747913/5720fb62-1352-4140-b0f6-93c818689660) The `margin-left` should be applied only to `.euiBottomBar--fixed` instead of all `.euiBottomBar`, `--sticky` and `--static` are already positioned correctly to the relative parent, so no margin needs to be applied. --- src/core/public/styles/_base.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/public/styles/_base.scss b/src/core/public/styles/_base.scss index 090ce072545cef..4cc9c48c726661 100644 --- a/src/core/public/styles/_base.scss +++ b/src/core/public/styles/_base.scss @@ -26,8 +26,8 @@ margin-left: 320px; // Hard-coded for now -- @cchaos } -// Add support for serverless nabbar -.euiBody--hasFlyout .euiBottomBar { +// Add support for serverless navbar +.euiBody--hasFlyout .euiBottomBar--fixed { margin-left: var(--euiCollapsibleNavOffset, 0); }