Skip to content

Commit

Permalink
[Response Ops][Alerting] Enable framework alerts as data by default (#…
Browse files Browse the repository at this point in the history
…154076)

## Summary

Setting `xpack.alerting.enableFrameworkAlerts` to true by default. This
causes alerts-as-data resource installation to be handled by the
alerting plugin and not the rule registry. We're keeping the feature
flag in case we run into issues but eventually we'll clean up the code
to remove the feature flag and clean up the rule registry code that
relies on the feature flag. Changing this default setting early will
allow us to identify issues before the 8.8 FF where we can revert if
needed.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
ymao1 and kibanamachine authored Apr 4, 2023
1 parent 5537414 commit 3b951e1
Show file tree
Hide file tree
Showing 24 changed files with 85 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { ElasticsearchClient } from '../elasticsearch_client';
export const deleteAllIndex = async (
esClient: ElasticsearchClient,
pattern: string,
specifyAlias: boolean = false,
maxAttempts = 5
): Promise<boolean> => {
for (let attempt = 1; ; attempt++) {
Expand All @@ -22,9 +23,14 @@ export const deleteAllIndex = async (

// resolve pattern to concrete index names
const { body: resp } = await esClient.indices.getAlias(
{
index: pattern,
},
specifyAlias
? {
name: pattern,
index: `${pattern}-*`,
}
: {
index: pattern,
},
{ ignore: [404], meta: true }
);

Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/alerting/server/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('config validation', () => {
expect(configSchema.validate(config)).toMatchInlineSnapshot(`
Object {
"cancelAlertsOnRuleTimeout": true,
"enableFrameworkAlerts": false,
"enableFrameworkAlerts": true,
"healthCheck": Object {
"interval": "60m",
},
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/alerting/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const configSchema = schema.object({
maxEphemeralActionsPerAlert: schema.number({
defaultValue: DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT,
}),
enableFrameworkAlerts: schema.boolean({ defaultValue: false }),
enableFrameworkAlerts: schema.boolean({ defaultValue: true }),
cancelAlertsOnRuleTimeout: schema.boolean({ defaultValue: true }),
rules: rulesSchema,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { HOSTS_URL, TIMELINES_URL } from '../../urls/navigation';
import {
addIndexToDefault,
clickAlertCheckbox,
deleteAlertsIndex,
deselectSourcererOptions,
isDataViewSelection,
isHostsStatValue,
Expand All @@ -23,9 +22,9 @@ import {
openAdvancedSettings,
openDataViewSelection,
openSourcerer,
refreshUntilAlertsIndexExists,
resetSourcerer,
saveSourcerer,
waitForAlertsIndexToExist,
} from '../../tasks/sourcerer';
import { postDataView } from '../../tasks/common';
import { openTimelineUsingToggle } from '../../tasks/security_main';
Expand All @@ -46,7 +45,6 @@ const dataViews = ['auditbeat-*,fakebeat-*', 'auditbeat-*,*beat*,siem-read*,.kib
describe('Sourcerer', () => {
before(() => {
esArchiverResetKibana();
deleteAlertsIndex();
dataViews.forEach((dataView: string) => postDataView(dataView));
});
describe('permissions', () => {
Expand Down Expand Up @@ -144,19 +142,13 @@ describe('Timeline scope', () => {
visit(TIMELINES_URL);
});

it('correctly loads SIEM data view before and after signals index exists', () => {
it('correctly loads SIEM data view', () => {
openTimelineUsingToggle();
openSourcerer('timeline');
isDataViewSelection(siemDataViewTitle);
openAdvancedSettings();
isSourcererSelection(`auditbeat-*`);
isNotSourcererSelection(`${DEFAULT_ALERTS_INDEX}-default`);
isSourcererOptions(
[...DEFAULT_INDEX_PATTERN, `${DEFAULT_ALERTS_INDEX}-default`].filter(
(pattern) => pattern !== 'auditbeat-*'
)
);
waitForAlertsIndexToExist();
isSourcererSelection(`${DEFAULT_ALERTS_INDEX}-default`);
isSourcererOptions(DEFAULT_INDEX_PATTERN.filter((pattern) => pattern !== 'auditbeat-*'));
isNotSourcererOption(`${DEFAULT_ALERTS_INDEX}-default`);
});
Expand Down Expand Up @@ -211,7 +203,7 @@ describe('Timeline scope', () => {
});
beforeEach(() => {
visit(TIMELINES_URL);
waitForAlertsIndexToExist();
refreshUntilAlertsIndexExists();
});
it('Modifies timeline to alerts only, and switches to different saved timeline without issue', function () {
openTimelineById(this.timelineId).then(() => {
Expand Down
30 changes: 1 addition & 29 deletions x-pack/plugins/security_solution/cypress/tasks/sourcerer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { HOSTS_URL } from '../urls/navigation';
import { waitForPage } from './login';
import { openTimelineUsingToggle } from './security_main';
import { DEFAULT_ALERTS_INDEX } from '../../common/constants';
import { createRule } from './api_calls/rules';
import { getNewRule } from '../objects/rule';

export const openSourcerer = (sourcererScope?: string) => {
if (sourcererScope != null && sourcererScope === 'timeline') {
Expand Down Expand Up @@ -115,28 +113,7 @@ export const addIndexToDefault = (index: string) => {
});
};

export const deleteAlertsIndex = () => {
const alertsIndexUrl = `${Cypress.env(
'ELASTICSEARCH_URL'
)}/.internal.alerts-security.alerts-default-000001`;

cy.request({
url: alertsIndexUrl,
method: 'GET',
headers: { 'kbn-xsrf': 'cypress-creds' },
failOnStatusCode: false,
}).then((response) => {
if (response.status === 200) {
cy.request({
url: alertsIndexUrl,
method: 'DELETE',
headers: { 'kbn-xsrf': 'cypress-creds' },
});
}
});
};

const refreshUntilAlertsIndexExists = async () => {
export const refreshUntilAlertsIndexExists = async () => {
cy.waitUntil(
() => {
cy.reload();
Expand All @@ -153,11 +130,6 @@ const refreshUntilAlertsIndexExists = async () => {
);
};

export const waitForAlertsIndexToExist = () => {
createRule(getNewRule({ rule_id: '1', max_signals: 100 }));
refreshUntilAlertsIndexExists();
};

export const deleteRuntimeField = (dataView: string, fieldName: string) => {
const deleteRuntimeFieldPath = `/api/data_views/data_view/${dataView}/runtime_field/${fieldName}`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const deleteIndexRoute = (router: SecuritySolutionPluginRouter) => {
body: `index: "${index}" does not exist`,
});
} else {
await deleteAllIndex(esClient, index);
await deleteAllIndex(esClient, index, true);
const policyExists = await getPolicyExists(esClient, index);
if (policyExists) {
await deletePolicy(esClient, index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function alertTests({ getService }: FtrProviderContext) {
after(async () => {
await esTestIndexTool.destroy();
await es.indices.delete({ index: authorizationIndex });
await es.indices.delete({ index: alertAsDataIndex });
await es.deleteByQuery({ index: alertAsDataIndex, query: { match_all: {} } });
});

for (const scenario of UserAtSpaceScenarios) {
Expand Down
4 changes: 2 additions & 2 deletions x-pack/test/api_integration/apis/maps/maps_telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export default function ({ getService }: FtrProviderContext) {
return fieldStat.name === 'geo_point';
}
);
expect(geoPointFieldStats.count).to.be(7);
expect(geoPointFieldStats.index_count).to.be(6);
expect(geoPointFieldStats.count).to.be(39);
expect(geoPointFieldStats.index_count).to.be(10);

const geoShapeFieldStats = apiResponse.cluster_stats.indices.mappings.field_types.find(
(fieldStat: estypes.ClusterStatsFieldTypes) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
await synthtraceEsClient.clean();
await supertest.delete(`/api/alerting/rule/${ruleId}`).set('kbn-xsrf', 'foo');
await supertest.delete(`/api/actions/connector/${actionId}`).set('kbn-xsrf', 'foo');
await esDeleteAllIndices(['.alerts*', INDEX_NAME]);
await esDeleteAllIndices(INDEX_NAME);
await es.deleteByQuery({ index: '.alerts*', query: { match_all: {} } });
await es.deleteByQuery({
index: '.kibana-event-log-*',
query: { term: { 'kibana.alert.rule.consumer': 'apm' } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const apmApiClient = getService('apmApiClient');
const supertest = getService('supertest');
const synthtraceEsClient = getService('synthtraceEsClient');
const esDeleteAllIndices = getService('esDeleteAllIndices');
const esClient = getService('es');
const log = getService('log');
const start = Date.now() - 24 * 60 * 60 * 1000;
Expand Down Expand Up @@ -90,7 +89,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {

after(async () => {
await supertest.delete(`/api/alerting/rule/${ruleId}`).set('kbn-xsrf', 'true');
await esDeleteAllIndices('.alerts*');
await esClient.deleteByQuery({ index: '.alerts*', query: { match_all: {} } });
});

it('returns the correct number of alerts', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) {
const apmApiClient = getService('apmApiClient');
const supertest = getService('supertest');
const synthtraceEsClient = getService('synthtraceEsClient');
const esDeleteAllIndices = getService('esDeleteAllIndices');
const esClient = getService('es');
const log = getService('log');
const start = Date.now() - 24 * 60 * 60 * 1000;
Expand Down Expand Up @@ -122,7 +121,7 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) {

after(async () => {
await supertest.delete(`/api/alerting/rule/${ruleId}`).set('kbn-xsrf', 'true');
await esDeleteAllIndices('.alerts*');
await esClient.deleteByQuery({ index: '.alerts*', query: { match_all: {} } });
});

it('returns the correct number of alerts', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,6 @@ export default ({ getService }: FtrProviderContext) => {

describe('query_signals_route and find_alerts_route', () => {
describe('validation checks', () => {
it('should not give errors when querying and the signals index does not exist yet', async () => {
const { body } = await supertest
.post(DETECTION_ENGINE_QUERY_SIGNALS_URL)
.set('kbn-xsrf', 'true')
.send(getSignalStatus())
.expect(200);

// remove any server generated items that are indeterministic
delete body.took;

expect(body).to.eql({
timed_out: false,
_shards: { total: 0, successful: 0, skipped: 0, failed: 0 },
hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] },
});
});

// This fails and should be investigated or removed if it no longer applies
it.skip('should not give errors when querying and the signals index does exist and is empty', async () => {
await createSignalsIndex(supertest, log);
Expand Down Expand Up @@ -144,23 +127,6 @@ export default ({ getService }: FtrProviderContext) => {

describe('find_alerts_route', () => {
describe('validation checks', () => {
it('should not give errors when querying and the signals index does not exist yet', async () => {
const { body } = await supertest
.post(ALERTS_AS_DATA_FIND_URL)
.set('kbn-xsrf', 'true')
.send({ ...getSignalStatus(), index: '.siem-signals-default' })
.expect(200);

// remove any server generated items that are indeterministic
delete body.took;

expect(body).to.eql({
timed_out: false,
_shards: { total: 0, successful: 0, skipped: 0, failed: 0 },
hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] },
});
});

// This fails and should be investigated or removed if it no longer applies
it.skip('should not give errors when querying and the signals index does exist and is empty', async () => {
await createSignalsIndex(supertest, log);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ export default ({ getService }: FtrProviderContext): void => {
const supertestWithoutAuth = getService('supertestWithoutAuth');
const log = getService('log');

const getSignalsMigrationStatus = async (query: any) => {
const { body } = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query(query)
.set('kbn-xsrf', 'true')
.expect(200);

const filteredIndices = body.indices.filter(
(index: any) => index?.index !== '.internal.alerts-security.alerts-default-000001'
);
return filteredIndices;
};

describe('Finalizing signals migrations', () => {
let legacySignalsIndexName: string;
let outdatedSignalsIndexName: string;
Expand Down Expand Up @@ -93,12 +106,9 @@ export default ({ getService }: FtrProviderContext): void => {
});

it('replaces the original index alias with the migrated one', async () => {
const { body } = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query({ from: '2020-10-10' })
.set('kbn-xsrf', 'true')
.expect(200);
const statusResponses: StatusResponse[] = body.indices;
const statusResponses: StatusResponse[] = await getSignalsMigrationStatus({
from: '2020-10-10',
});
const indicesBefore = statusResponses.map((index) => index.index);

expect(indicesBefore).to.contain(createdMigration.index);
Expand Down Expand Up @@ -170,17 +180,11 @@ export default ({ getService }: FtrProviderContext): void => {
log
);

const { body: bodyAfter } = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query({ from: '2020-10-10' })
.set('kbn-xsrf', 'true')
.expect(200);

const statusAfter: StatusResponse[] = bodyAfter.indices;
expect(statusAfter.map((s) => s.index)).to.eql([
const indices = await getSignalsMigrationStatus({ from: '2020-10-10' });
expect(indices.map((s: any) => s.index)).to.eql([
...createdMigrations.map((c) => c.migration_index),
]);
expect(statusAfter.map((s) => s.is_outdated)).to.eql([false, false]);
expect(indices.map((s: any) => s.is_outdated)).to.eql([false, false]);
});

// This fails and should be investigated or removed if it no longer applies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ export default ({ getService }: FtrProviderContext): void => {
const supertestWithoutAuth = getService('supertestWithoutAuth');
const log = getService('log');

const getSignalsMigrationStatus = async (query: any) => {
const { body } = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query(query)
.set('kbn-xsrf', 'true')
.expect(200);

const filteredIndices = body.indices.filter(
(index: any) => index?.index !== '.internal.alerts-security.alerts-default-000001'
);
return filteredIndices;
};

describe('Signals migration status', () => {
let legacySignalsIndexName: string;
beforeEach(async () => {
Expand All @@ -35,24 +48,12 @@ export default ({ getService }: FtrProviderContext): void => {
});

it('returns no indexes if no signals exist in the specified range', async () => {
const { body } = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query({ from: '2020-10-20' })
.set('kbn-xsrf', 'true')
.expect(200);

expect(body.indices).to.eql([]);
const indices = await getSignalsMigrationStatus({ from: '2020-10-20' });
expect(indices).to.eql([]);
});

it('includes an index if its signals are within the specified range', async () => {
const {
body: { indices },
} = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query({ from: '2020-10-10' })
.set('kbn-xsrf', 'true')
.expect(200);

const indices = await getSignalsMigrationStatus({ from: '2020-10-10' });
expect(indices).length(1);
expect(indices[0].index).to.eql(legacySignalsIndexName);
});
Expand All @@ -62,13 +63,8 @@ export default ({ getService }: FtrProviderContext): void => {
await esArchiver.load('x-pack/test/functional/es_archives/signals/outdated_signals_index')
);

const { body } = await supertest
.get(DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL)
.query({ from: '2020-10-10' })
.set('kbn-xsrf', 'true')
.expect(200);

expect(body.indices).to.eql([
const indices = await getSignalsMigrationStatus({ from: '2020-10-10' });
expect(indices).to.eql([
{
index: legacySignalsIndexName,
is_outdated: true,
Expand Down
Loading

0 comments on commit 3b951e1

Please sign in to comment.