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

WIP #9

Closed
wants to merge 2 commits into from
Closed
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
29 changes: 18 additions & 11 deletions x-pack/plugins/rule_registry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ On plugin setup, rule type producers can create the index template as follows:
```ts
// get the FQN of the component template. All assets are prefixed with the configured `index` value, which is `.alerts` by default.

const componentTemplateName = plugins.ruleRegistry.getFullAssetName(
'apm-mappings'
);
const componentTemplateName = plugins.ruleRegistry.getFullAssetName('apm-mappings');

// if write is disabled, don't install these templates
if (!plugins.ruleRegistry.isWriteEnabled()) {
Expand Down Expand Up @@ -73,14 +71,10 @@ await plugins.ruleRegistry.createOrUpdateComponentTemplate({
await plugins.ruleRegistry.createOrUpdateIndexTemplate({
name: plugins.ruleRegistry.getFullAssetName('apm-index-template'),
body: {
index_patterns: [
plugins.ruleRegistry.getFullAssetName('observability-apm*'),
],
index_patterns: [plugins.ruleRegistry.getFullAssetName('observability-apm*')],
composed_of: [
// Technical component template, required
plugins.ruleRegistry.getFullAssetName(
TECHNICAL_COMPONENT_TEMPLATE_NAME
),
plugins.ruleRegistry.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME),
componentTemplateName,
],
},
Expand All @@ -107,8 +101,7 @@ await ruleDataClient.getWriter().bulk({
// to read data, simply call ruleDataClient.getReader().search:
const response = await ruleDataClient.getReader().search({
body: {
query: {
},
query: {},
size: 100,
fields: ['*'],
collapse: {
Expand All @@ -135,6 +128,7 @@ The following fields are defined in the technical field component template and s
- `rule.name`: the name of the rule (as specified by the user).
- `rule.category`: the name of the rule type (as defined by the rule type producer)
- `kibana.rac.alert.producer`: the producer of the rule type. Usually a Kibana plugin. e.g., `APM`.
- `kibana.rac.alert.owner`: the feature which produced the alert. Usually a Kibana feature id like `apm`, `siem`...
- `kibana.rac.alert.id`: the id of the alert, that is unique within the context of the rule execution it was created in. E.g., for a rule that monitors latency for all services in all environments, this might be `opbeans-java:production`.
- `kibana.rac.alert.uuid`: the unique identifier for the alert during its lifespan. If an alert recovers (or closes), this identifier is re-generated when it is opened again.
- `kibana.rac.alert.status`: the status of the alert. Can be `open` or `closed`.
Expand All @@ -148,3 +142,16 @@ The following fields are defined in the technical field component template and s
- `kibana.rac.alert.ancestors`: the array of ancestors (if any) for the alert.
- `kibana.rac.alert.depth`: the depth of the alert in the ancestral tree (default 0).
- `kibana.rac.alert.building_block_type`: the building block type of the alert (default undefined).

# Alerts as data

Alerts as data can be interacted with using the AlertsClient api found in `x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts`

This api includes public methods such as

[x] getFullAssetName
[x] getAlertsIndex
[x] get
[x] update
[ ] bulkUpdate (TODO)
[ ] find (TODO)
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export class AlertsClient {
);
}

// pull concrete index name off of document
private async fetchAlert({ id, indexName }: GetAlertParams): Promise<ParsedTechnicalFields> {
try {
const result = await this.esClient.get<ParsedTechnicalFields>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ cd ./hunter && sh ./post_detections_role.sh && sh ./post_detections_user.sh
cd ../observer && sh ./post_detections_role.sh && sh ./post_detections_user.sh
cd ..

# curl get_index script

# Example: ./find_rules.sh
curl -v -k \
-u $USER:changeme \
-X GET "${KIBANA_URL}${SPACE_URL}/api/rac/alerts?id=NoxgpHkBqbdrfX07MqXV&assetName=observability-apm" | jq .
-X GET "${KIBANA_URL}${SPACE_URL}/api/rac/alerts?id=NoxgpHkBqbdrfX07MqXV&indexName=.alerts-observability-apm" | jq .
60 changes: 58 additions & 2 deletions x-pack/test/api_integration/apis/security_solution/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

import expect from '@kbn/expect';

import { secOnly } from '../../../rule_registry/common/lib/authentication/users';
import {
createSpacesAndUsers,
deleteSpacesAndUsers,
} from '../../../rule_registry/common/lib/authentication/';
import {
Direction,
TimelineEventsQueries,
Expand Down Expand Up @@ -407,10 +412,21 @@ export default function ({ getService }: FtrProviderContext) {
const retry = getService('retry');
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');

describe('Timeline', () => {
before(() => esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'));
after(() => esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'));
// before(() => esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'));
// after(() => esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'));
before(async () => {
await esArchiver.load('auditbeat/hosts');
await esArchiver.load('rule_registry/alerts');
await createSpacesAndUsers(getService);
});
after(async () => {
await esArchiver.unload('auditbeat/hosts');
await esArchiver.load('rule_registry/alerts');
await deleteSpacesAndUsers(getService);
});

it('Make sure that we get Timeline data', async () => {
await retry.try(async () => {
Expand Down Expand Up @@ -454,6 +470,46 @@ export default function ({ getService }: FtrProviderContext) {
});
});

it.skip('Make sure that we get Timeline data using the hunter role and do not receive observability alerts', async () => {
await retry.try(async () => {
const resp = await supertestWithoutAuth
.post('/internal/search/securitySolutionTimelineSearchStrategy/')
.auth(secOnly.username, secOnly.password)
.set('kbn-xsrf', 'true')
.set('Content-Type', 'application/json')
.send({
defaultIndex: ['.alerts*'], // query both .alerts-observability-apm and .alerts-security-solution
docValueFields: DOC_VALUE_FIELDS,
factoryQueryType: TimelineEventsQueries.all,
fieldRequested: FIELD_REQUESTED,
fields: [],
filterQuery: FILTER_VALUE,
pagination: {
activePage: 0,
querySize: 25,
},
language: 'kuery',
sort: [
{
field: '@timestamp',
direction: Direction.desc,
type: 'number',
},
],
timerange: {
from: FROM,
to: TO,
interval: '12h',
},
})
.expect(200);

const timeline = resp.body;

expect(timeline.totalCount).to.be(1);
});
});

it('Make sure that pagination is working in Timeline query', async () => {
await retry.try(async () => {
const resp = await supertest
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/api_integration/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi
);

return {
testFiles: [require.resolve('./apis')],
testFiles: [require.resolve('./apis/security_solution/events')],
services,
servers: xPackFunctionalTestsConfig.get('servers'),
security: xPackFunctionalTestsConfig.get('security'),
Expand Down
15 changes: 15 additions & 0 deletions x-pack/test/functional/es_archives/rule_registry/alerts/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,25 @@
"index": ".alerts-observability-apm",
"id": "NoxgpHkBqbdrfX07MqXV",
"source": {
"@timestamp": "2020-12-16T15:16:18.570Z",
"rule.id": "apm.error_rate",
"message": "hello world 1",
"kibana.rac.alert.owner": "apm",
"kibana.rac.alert.status": "open"
}
}
}
{
"type": "doc",
"value": {
"index": ".alerts-security-solution",
"id": "020202",
"source": {
"@timestamp": "2020-12-16T15:16:18.570Z",
"rule.id": "siem.signals",
"message": "hello world security",
"kibana.rac.alert.owner": "siem",
"kibana.rac.alert.status": "open"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,27 @@
}
}
}

{
"type": "index",
"value": {
"index": ".alerts-security-solution",
"mappings": {
"properties": {
"message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"kibana.rac.alert.owner": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}