Skip to content

Commit

Permalink
Merge branch 'main' into role-mgmt-descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
lcawl authored May 29, 2024
2 parents deca968 + b34ff52 commit 2f8f05b
Show file tree
Hide file tree
Showing 67 changed files with 1,395 additions and 112 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/
/x-pack/plugins/security_solution/public/detection_engine/rule_creation @elastic/security-detection-engine
/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui @elastic/security-detection-engine
/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions @elastic/security-detection-engine
/x-pack/plugins/security_solution/public/detection_engine/rule_gaps @elastic/security-detection-engine
/x-pack/plugins/security_solution/public/detections/containers/detection_engine/lists @elastic/security-detection-engine
/x-pack/plugins/security_solution/public/detections/pages/alerts @elastic/security-detection-engine
/x-pack/plugins/security_solution/public/exceptions @elastic/security-detection-engine
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export const OBSERVABILITY_ONBOARDING_LOCATOR = 'OBSERVABILITY_ONBOARDING_LOCATO
export interface ObservabilityOnboardingLocatorParams extends SerializableRecord {
/** If given, it will load the given map else will load the create a new map page. */
source?: 'customLogs' | 'systemLogs';
category?: string;
}
5 changes: 5 additions & 0 deletions x-pack/plugins/alerting/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ export const INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH =
export const INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH =
`${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/_active` as const;

export const INTERNAL_ALERTING_BACKFILL_API_PATH =
`${INTERNAL_BASE_ALERTING_API_PATH}/rules/backfill` as const;
export const INTERNAL_ALERTING_BACKFILL_FIND_API_PATH =
`${INTERNAL_ALERTING_BACKFILL_API_PATH}/_find` as const;

export const ALERTING_FEATURE_ID = 'alerts';
export const MONITORING_HISTORY_LIMIT = 200;
export const ENABLE_MAINTENANCE_WINDOWS = true;
Original file line number Diff line number Diff line change
Expand Up @@ -1253,16 +1253,10 @@ describe('Alerts Service', () => {
TestRegistrationContext.context,
DEFAULT_NAMESPACE_STRING
)
).toEqual({
error:
'Failure during installation. Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default',
result: false,
});
).toEqual({ result: true });

expect(logger.error).toHaveBeenCalledWith(
new Error(
`Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default`
)
expect(logger.debug).toHaveBeenCalledWith(
`Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default`
);

expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks';
import { errors as EsErrors } from '@elastic/elasticsearch';
import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { createConcreteWriteIndex } from './create_concrete_write_index';
import { createConcreteWriteIndex, setConcreteWriteIndex } from './create_concrete_write_index';
import { getDataStreamAdapter } from './data_stream_adapter';

const randomDelayMultiplier = 0.01;
Expand Down Expand Up @@ -680,7 +680,7 @@ describe('createConcreteWriteIndex', () => {
}
});

it(`should throw error when there are concrete indices but none of them are the write index`, async () => {
it(`should log an error and try to set write index when there are concrete indices but none of them are the write index`, async () => {
if (useDataStream) return;

clusterClient.indices.getAlias.mockImplementationOnce(async () => ({
Expand All @@ -701,18 +701,101 @@ describe('createConcreteWriteIndex', () => {
async () => SimulateTemplateResponse
);

await expect(() =>
createConcreteWriteIndex({
logger,
esClient: clusterClient,
indexPatterns: IndexPatterns,
totalFieldsLimit: 2500,
dataStreamAdapter,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default"`
await createConcreteWriteIndex({
logger,
esClient: clusterClient,
indexPatterns: IndexPatterns,
totalFieldsLimit: 2500,
dataStreamAdapter,
});

expect(logger.debug).toHaveBeenCalledWith(
'Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default'
);
expect(clusterClient.indices.updateAliases).toHaveBeenCalled();
});
});
}
});

describe('setConcreteWriteIndex', () => {
beforeEach(() => {
jest.resetAllMocks();
});

it(`should call updateAliases to set the concrete write index`, async () => {
await setConcreteWriteIndex({
logger,
esClient: clusterClient,
concreteIndices: [
{
index: '.internal.alerts-test.alerts-default-000003',
alias: '.alerts-test.alerts-default',
isWriteIndex: false,
},
{
index: '.internal.alerts-test.alerts-default-000004',
alias: '.alerts-test.alerts-default',
isWriteIndex: false,
},
{
index: '.internal.alerts-test.alerts-default-000001',
alias: '.alerts-test.alerts-default',
isWriteIndex: false,
},
{
index: '.internal.alerts-test.alerts-default-000002',
alias: '.alerts-test.alerts-default',
isWriteIndex: false,
},
],
});

expect(logger.debug).toHaveBeenCalledWith(
'Attempting to set index: .internal.alerts-test.alerts-default-000004 as the write index for alias: .alerts-test.alerts-default.'
);
expect(clusterClient.indices.updateAliases).toHaveBeenCalledWith({
body: {
actions: [
{
remove: {
alias: '.alerts-test.alerts-default',
index: '.internal.alerts-test.alerts-default-000004',
},
},
{
add: {
alias: '.alerts-test.alerts-default',
index: '.internal.alerts-test.alerts-default-000004',
is_write_index: true,
},
},
],
},
});
expect(logger.info).toHaveBeenCalledWith(
'Successfully set index: .internal.alerts-test.alerts-default-000004 as the write index for alias: .alerts-test.alerts-default.'
);
});

it(`should throw an error if there is a failure setting the concrete write index`, async () => {
const error = new Error(`fail`) as EsError;
clusterClient.indices.updateAliases.mockRejectedValueOnce(error);

await expect(() =>
setConcreteWriteIndex({
logger,
esClient: clusterClient,
concreteIndices: [
{
index: '.internal.alerts-test.alerts-default-000001',
alias: '.alerts-test.alerts-default',
isWriteIndex: false,
},
],
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Failed to set index: .internal.alerts-test.alerts-default-000001 as the write index for alias: .alerts-test.alerts-default."`
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { IndicesSimulateIndexTemplateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { Logger, ElasticsearchClient } from '@kbn/core/server';
import { get } from 'lodash';
import { get, sortBy } from 'lodash';
import { IIndexPatternString } from '../resource_installer_utils';
import { retryTransientEsErrors } from './retry_transient_es_errors';
import { DataStreamAdapter } from './data_stream_adapter';
Expand Down Expand Up @@ -165,3 +165,45 @@ export interface CreateConcreteWriteIndexOpts {
export const createConcreteWriteIndex = async (opts: CreateConcreteWriteIndexOpts) => {
await opts.dataStreamAdapter.createStream(opts);
};

interface SetConcreteWriteIndexOpts {
logger: Logger;
esClient: ElasticsearchClient;
concreteIndices: ConcreteIndexInfo[];
}

export async function setConcreteWriteIndex(opts: SetConcreteWriteIndexOpts) {
const { logger, esClient, concreteIndices } = opts;
const lastIndex = concreteIndices.length - 1;
const concreteIndex = sortBy(concreteIndices, ['index'])[lastIndex];
logger.debug(
`Attempting to set index: ${concreteIndex.index} as the write index for alias: ${concreteIndex.alias}.`
);
try {
await retryTransientEsErrors(
() =>
esClient.indices.updateAliases({
body: {
actions: [
{ remove: { index: concreteIndex.index, alias: concreteIndex.alias } },
{
add: {
index: concreteIndex.index,
alias: concreteIndex.alias,
is_write_index: true,
},
},
],
},
}),
{ logger }
);
logger.info(
`Successfully set index: ${concreteIndex.index} as the write index for alias: ${concreteIndex.alias}.`
);
} catch (error) {
throw new Error(
`Failed to set index: ${concreteIndex.index} as the write index for alias: ${concreteIndex.alias}.`
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
CreateConcreteWriteIndexOpts,
ConcreteIndexInfo,
updateIndexMappings,
setConcreteWriteIndex,
} from './create_concrete_write_index';
import { retryTransientEsErrors } from './retry_transient_es_errors';

Expand Down Expand Up @@ -186,9 +187,11 @@ async function createAliasStream(opts: CreateConcreteWriteIndexOpts): Promise<vo
// If there are some concrete indices but none of them are the write index, we'll throw an error
// because one of the existing indices should have been the write target.
if (concreteIndicesExist && !concreteWriteIndicesExist) {
throw new Error(
logger.debug(
`Indices matching pattern ${indexPatterns.pattern} exist but none are set as the write index for alias ${indexPatterns.alias}`
);
await setConcreteWriteIndex({ logger, esClient, concreteIndices });
concreteWriteIndicesExist = true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
} from '../../../../../common/routes/backfill/apis/find';
import { ILicenseState } from '../../../../lib';
import { verifyAccessAndContext } from '../../../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_BACKFILL_FIND_API_PATH,
} from '../../../../types';
import { transformRequestV1, transformResponseV1 } from './transforms';

export const findBackfillRoute = (
Expand All @@ -21,7 +24,7 @@ export const findBackfillRoute = (
) => {
router.post(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/backfill/_find`,
path: `${INTERNAL_ALERTING_BACKFILL_FIND_API_PATH}`,
validate: {
query: findQuerySchemaV1,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const getCasesByAlertIdRoute = createCasesRoute({
alert_id: schema.string({ minLength: 1 }),
}),
},
routerOptions: {
access: 'public',
description: `Get cases for an alert`,
},
handler: async ({ context, request, response }) => {
try {
const alertID = request.params.alert_id;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/delete_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import { createCasesRoute } from '../create_cases_route';
export const deleteCaseRoute = createCasesRoute({
method: 'delete',
path: CASES_URL,
routerOptions: {
access: 'public',
description: `Delete cases`,
},
params: {
query: schema.object({
ids: schema.arrayOf(schema.string()),
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/find_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import type { caseApiV1 } from '../../../../common/types/api';
export const findCaseRoute = createCasesRoute({
method: 'get',
path: `${CASES_URL}/_find`,
routerOptions: {
access: 'public',
description: `Search cases`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/get_case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export const getCaseRoute = createCasesRoute({
method: 'get',
path: CASE_DETAILS_URL,
params,
routerOptions: {
access: 'public',
description: `Get a case`,
},
handler: async ({ context, request, response, logger, kibanaVersion }) => {
try {
const isIncludeCommentsParamProvidedByTheUser =
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/patch_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import type { caseDomainV1 } from '../../../../common/types/domain';
export const patchCaseRoute = createCasesRoute({
method: 'patch',
path: CASES_URL,
routerOptions: {
access: 'public',
description: `Update cases`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/post_case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import type { caseDomainV1 } from '../../../../common/types/domain';
export const postCaseRoute = createCasesRoute({
method: 'post',
path: CASES_URL,
routerOptions: {
access: 'public',
description: `Create a case`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/push_case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import type { caseDomainV1 } from '../../../../common/types/domain';
export const pushCaseRoute: CaseRoute = createCasesRoute({
method: 'post',
path: CASE_PUSH_URL,
routerOptions: {
access: 'public',
description: `Push a case to an external service`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import type { caseApiV1 } from '../../../../../common/types/api';
export const getReportersRoute = createCasesRoute({
method: 'get',
path: CASE_REPORTERS_URL,
routerOptions: {
access: 'public',
description: `Get all case creators`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/server/routes/api/cases/tags/get_tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import type { caseApiV1 } from '../../../../../common/types/api';
export const getTagsRoute = createCasesRoute({
method: 'get',
path: CASE_TAGS_URL,
routerOptions: {
access: 'public',
description: `Get case tags`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import { createCaseError } from '../../../common/error';
export const deleteAllCommentsRoute = createCasesRoute({
method: 'delete',
path: CASE_COMMENTS_URL,
routerOptions: {
access: 'public',
description: `Delete all alerts and comments from a case`,
},
params: {
params: schema.object({
case_id: schema.string(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export const deleteCommentRoute = createCasesRoute({
comment_id: schema.string(),
}),
},
routerOptions: {
access: 'public',
description: `Delete an alert or comment from a case`,
},
handler: async ({ context, request, response }) => {
try {
const caseContext = await context.cases;
Expand Down
Loading

0 comments on commit 2f8f05b

Please sign in to comment.