Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SIEM] Fixes toaster errors when siemDefault index is an empty or empty spaces #73991

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { filterIndexes } from './resolvers';

describe('resolvers', () => {
test('it should filter single index that has an empty string', () => {
const emptyArray = filterIndexes(['']);
expect(emptyArray).toEqual([]);
});

test('it should filter single index that has blanks within it', () => {
const emptyArray = filterIndexes([' ']);
expect(emptyArray).toEqual([]);
});

test('it should filter indexes that has an empty string and a valid index', () => {
const emptyArray = filterIndexes(['', 'valid-index']);
expect(emptyArray).toEqual(['valid-index']);
});

test('it should filter indexes that have blanks within them and a valid index', () => {
const emptyArray = filterIndexes([' ', 'valid-index']);
expect(emptyArray).toEqual(['valid-index']);
});

test('it should filter single index that has _all within it', () => {
const emptyArray = filterIndexes(['_all']);
expect(emptyArray).toEqual([]);
});

test('it should filter single index that has _all within it surrounded by spaces', () => {
const emptyArray = filterIndexes([' _all ']);
expect(emptyArray).toEqual([]);
});

test('it should filter indexes that _all within them and a valid index', () => {
const emptyArray = filterIndexes(['_all', 'valid-index']);
expect(emptyArray).toEqual(['valid-index']);
});

test('it should filter indexes that _all surrounded with spaces within them and a valid index', () => {
const emptyArray = filterIndexes([' _all ', 'valid-index']);
expect(emptyArray).toEqual(['valid-index']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,34 @@ export const createSourceStatusResolvers = (libs: {
};
} => ({
SourceStatus: {
async indicesExist(source, args, { req }) {
if (
args.defaultIndex.length === 1 &&
(args.defaultIndex[0] === '' || args.defaultIndex[0] === '_all')
) {
async indicesExist(_, args, { req }) {
const indexes = filterIndexes(args.defaultIndex);
if (indexes.length !== 0) {
return libs.sourceStatus.hasIndices(req, indexes);
} else {
return false;
}
return libs.sourceStatus.hasIndices(req, args.defaultIndex);
},
async indexFields(source, args, { req }) {
if (
args.defaultIndex.length === 1 &&
(args.defaultIndex[0] === '' || args.defaultIndex[0] === '_all')
) {
async indexFields(_, args, { req }) {
const indexes = filterIndexes(args.defaultIndex);
if (indexes.length !== 0) {
return libs.fields.getFields(req, indexes);
} else {
return [];
}
return libs.fields.getFields(req, args.defaultIndex);
},
},
});

/**
* Given a set of indexes this will remove anything that is:
* - blank or empty strings are removed as not valid indexes
* - _all is removed as that is not a valid index
* @param indexes Indexes with invalid values removed
*/
export const filterIndexes = (indexes: string[]): string[] =>
indexes.filter((index) => index.trim() !== '' && index.trim() !== '_all');

export const toIFieldSubTypeNonNullableScalar = new GraphQLScalarType({
name: 'IFieldSubType',
description: 'Represents value in index pattern field item',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,21 @@ import {
import { FrameworkAdapter, FrameworkRequest } from '../framework';
import { FieldsAdapter, IndexFieldDescriptor } from './types';

type IndexesAliasIndices = Record<string, string[]>;

export class ElasticsearchIndexFieldAdapter implements FieldsAdapter {
constructor(private readonly framework: FrameworkAdapter) {}

public async getIndexFields(request: FrameworkRequest, indices: string[]): Promise<IndexField[]> {
const indexPatternsService = this.framework.getIndexPatternsService(request);
const indexesAliasIndices: IndexesAliasIndices = indices.reduce(
(accumulator: IndexesAliasIndices, indice: string) => {
const key = getIndexAlias(indices, indice);
const indexesAliasIndices = indices.reduce<Record<string, string[]>>((accumulator, indice) => {
const key = getIndexAlias(indices, indice);

if (get(key, accumulator)) {
accumulator[key] = [...accumulator[key], indice];
} else {
accumulator[key] = [indice];
}
return accumulator;
},
{} as IndexesAliasIndices
);
if (get(key, accumulator)) {
accumulator[key] = [...accumulator[key], indice];
} else {
accumulator[key] = [indice];
}
return accumulator;
}, {});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: These were just Type fixes and aren't directly related to this PR. More of a, "while I'm here I should fix this type with this reduce to be correct rather than as casted"

const responsesIndexFields: IndexFieldDescriptor[][] = await Promise.all(
Object.values(indexesAliasIndices).map((indicesByGroup) =>
indexPatternsService.getFieldsForWildcard({
Expand Down
107 changes: 91 additions & 16 deletions x-pack/test/api_integration/apis/security_solution/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,97 @@ export default function ({ getService }: FtrProviderContext) {
before(() => esArchiver.load('auditbeat/default'));
after(() => esArchiver.unload('auditbeat/default'));

it('Make sure that we get source information when auditbeat indices is there', () => {
return client
.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
docValueFields: [],
},
})
.then((resp) => {
const sourceStatus = resp.data.source.status;
// test data in x-pack/test/functional/es_archives/auditbeat_test_data/data.json.gz
expect(sourceStatus.indexFields.length).to.be(397);
expect(sourceStatus.indicesExist).to.be(true);
});
it('Make sure that we get source information when auditbeat indices is there', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
// test data in x-pack/test/functional/es_archives/auditbeat_test_data/data.json.gz
expect(sourceStatus.indexFields.length).to.be(397);
expect(sourceStatus.indicesExist).to.be(true);
});

it('should find indexes as being available when they exist', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
expect(sourceStatus.indicesExist).to.be(true);
});

it('should not find indexes as existing when there is an empty array of them', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: [],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
expect(sourceStatus.indicesExist).to.be(false);
});

it('should not find indexes as existing when there is a _all within it', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: ['_all'],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
expect(sourceStatus.indicesExist).to.be(false);
});

it('should not find indexes as existing when there are empty strings within it', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: [''],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
expect(sourceStatus.indicesExist).to.be(false);
});

it('should not find indexes as existing when there are blank spaces within it', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: [' '],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
expect(sourceStatus.indicesExist).to.be(false);
});

it('should find indexes when one is an empty index but the others are valid', async () => {
const resp = await client.query<SourceQuery.Query>({
query: sourceQuery,
variables: {
sourceId: 'default',
defaultIndex: ['', 'auditbeat-*'],
docValueFields: [],
},
});
const sourceStatus = resp.data.source.status;
expect(sourceStatus.indicesExist).to.be(true);
});
});
}