-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RAM] Category fields endpoint (#138245)
* first commit * get auth index and try field caps * use esClient * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * wait for promise to finish * format field capabilities * add simplier browserFields mapper * update response * refactor * types and refactor * remove browser fields dependency * update fn name * update types * update imported type package * update mock object * error message for no o11y alert indices * add endpoint integration test * activate commented tests * add unit test * comment uncommented tests * fix tests * review by Xavier * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * update param names + right type Co-authored-by: kibanamachine <[email protected]> Co-authored-by: Xavier Mouligneau <[email protected]>
- Loading branch information
1 parent
cc5ff75
commit f236196
Showing
10 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { FieldDescriptor } from '@kbn/data-views-plugin/server'; | ||
import { BrowserField, BrowserFields } from '../../types'; | ||
|
||
const getFieldCategory = (fieldCapability: FieldDescriptor) => { | ||
const name = fieldCapability.name.split('.'); | ||
|
||
if (name.length === 1) { | ||
return 'base'; | ||
} | ||
|
||
return name[0]; | ||
}; | ||
|
||
const browserFieldFactory = ( | ||
fieldCapability: FieldDescriptor, | ||
category: string | ||
): { [fieldName in string]: BrowserField } => { | ||
return { | ||
[fieldCapability.name]: { | ||
...fieldCapability, | ||
category, | ||
}, | ||
}; | ||
}; | ||
|
||
export const fieldDescriptorToBrowserFieldMapper = (fields: FieldDescriptor[]): BrowserFields => { | ||
return fields.reduce((browserFields: BrowserFields, field: FieldDescriptor) => { | ||
const category = getFieldCategory(field); | ||
const browserField = browserFieldFactory(field, category); | ||
|
||
if (browserFields[category]) { | ||
browserFields[category] = { fields: { ...browserFields[category].fields, ...browserField } }; | ||
} else { | ||
browserFields[category] = { fields: browserField }; | ||
} | ||
|
||
return browserFields; | ||
}, {}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; | ||
import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_feature_id'; | ||
import { requestContextMock } from './__mocks__/request_context'; | ||
import { getO11yBrowserFields } from './__mocks__/request_responses'; | ||
import { requestMock, serverMock } from './__mocks__/server'; | ||
|
||
describe('getBrowserFieldsByFeatureId', () => { | ||
let server: ReturnType<typeof serverMock.create>; | ||
let { clients, context } = requestContextMock.createTools(); | ||
const path = `${BASE_RAC_ALERTS_API_PATH}/browser_fields`; | ||
|
||
beforeEach(async () => { | ||
server = serverMock.create(); | ||
({ clients, context } = requestContextMock.createTools()); | ||
}); | ||
|
||
describe('when racClient returns o11y indices', () => { | ||
beforeEach(() => { | ||
clients.rac.getAuthorizedAlertsIndices.mockResolvedValue([ | ||
'.alerts-observability.logs.alerts-default', | ||
]); | ||
|
||
getBrowserFieldsByFeatureId(server.router); | ||
}); | ||
|
||
test('route registered', async () => { | ||
const response = await server.inject(getO11yBrowserFields(), context); | ||
|
||
expect(response.status).toEqual(200); | ||
}); | ||
|
||
test('rejects invalid featureId type', async () => { | ||
await expect( | ||
server.inject( | ||
requestMock.create({ | ||
method: 'get', | ||
path, | ||
query: { featureIds: undefined }, | ||
}), | ||
context | ||
) | ||
).rejects.toThrowErrorMatchingInlineSnapshot( | ||
`"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"featureIds\\"'"` | ||
); | ||
}); | ||
|
||
test('returns error status if rac client "getAuthorizedAlertsIndices" fails', async () => { | ||
clients.rac.getAuthorizedAlertsIndices.mockRejectedValue(new Error('Unable to get index')); | ||
const response = await server.inject(getO11yBrowserFields(), context); | ||
|
||
expect(response.status).toEqual(500); | ||
expect(response.body).toEqual({ | ||
attributes: { success: false }, | ||
message: 'Unable to get index', | ||
}); | ||
}); | ||
}); | ||
}); |
84 changes: 84 additions & 0 deletions
84
x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { IRouter } from '@kbn/core/server'; | ||
import { transformError } from '@kbn/securitysolution-es-utils'; | ||
import * as t from 'io-ts'; | ||
|
||
import { RacRequestHandlerContext } from '../types'; | ||
import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; | ||
import { buildRouteValidation } from './utils/route_validation'; | ||
|
||
export const getBrowserFieldsByFeatureId = (router: IRouter<RacRequestHandlerContext>) => { | ||
router.get( | ||
{ | ||
path: `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, | ||
validate: { | ||
query: buildRouteValidation( | ||
t.exact( | ||
t.type({ | ||
featureIds: t.union([t.string, t.array(t.string)]), | ||
}) | ||
) | ||
), | ||
}, | ||
options: { | ||
tags: ['access:rac'], | ||
}, | ||
}, | ||
async (context, request, response) => { | ||
try { | ||
const racContext = await context.rac; | ||
const alertsClient = await racContext.getAlertsClient(); | ||
const { featureIds = [] } = request.query; | ||
|
||
const indices = await alertsClient.getAuthorizedAlertsIndices( | ||
Array.isArray(featureIds) ? featureIds : [featureIds] | ||
); | ||
const o11yIndices = | ||
indices?.filter((index) => index.startsWith('.alerts-observability')) ?? []; | ||
if (o11yIndices.length === 0) { | ||
return response.notFound({ | ||
body: { | ||
message: `No alerts-observability indices found for featureIds [${featureIds}]`, | ||
attributes: { success: false }, | ||
}, | ||
}); | ||
} | ||
|
||
const browserFields = await alertsClient.getBrowserFields({ | ||
indices: o11yIndices, | ||
metaFields: ['_id', '_index'], | ||
allowNoIndex: true, | ||
}); | ||
|
||
return response.ok({ | ||
body: browserFields, | ||
}); | ||
} catch (error) { | ||
const formatedError = transformError(error); | ||
const contentType = { | ||
'content-type': 'application/json', | ||
}; | ||
const defaultedHeaders = { | ||
...contentType, | ||
}; | ||
|
||
return response.customError({ | ||
headers: defaultedHeaders, | ||
statusCode: formatedError.statusCode, | ||
body: { | ||
message: formatedError.message, | ||
attributes: { | ||
success: false, | ||
}, | ||
}, | ||
}); | ||
} | ||
} | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
...ck/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import expect from '@kbn/expect'; | ||
|
||
import { superUser, obsOnlySpacesAll, secOnlyRead } from '../../../common/lib/authentication/users'; | ||
import type { User } from '../../../common/lib/authentication/types'; | ||
import { FtrProviderContext } from '../../../common/ftr_provider_context'; | ||
import { getSpaceUrlPrefix } from '../../../common/lib/authentication/spaces'; | ||
|
||
// eslint-disable-next-line import/no-default-export | ||
export default ({ getService }: FtrProviderContext) => { | ||
const supertestWithoutAuth = getService('supertestWithoutAuth'); | ||
const esArchiver = getService('esArchiver'); | ||
const SPACE1 = 'space1'; | ||
const TEST_URL = '/internal/rac/alerts/browser_fields'; | ||
|
||
const getBrowserFieldsByFeatureId = async ( | ||
user: User, | ||
featureIds: string[], | ||
expectedStatusCode: number = 200 | ||
) => { | ||
const resp = await supertestWithoutAuth | ||
.get(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}`) | ||
.query({ featureIds }) | ||
.auth(user.username, user.password) | ||
.set('kbn-xsrf', 'true') | ||
.expect(expectedStatusCode); | ||
return resp.body; | ||
}; | ||
|
||
describe('Alert - Get browser fields by featureId', () => { | ||
before(async () => { | ||
await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); | ||
}); | ||
|
||
describe('Users:', () => { | ||
it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y featureIds`, async () => { | ||
const browserFields = await getBrowserFieldsByFeatureId(obsOnlySpacesAll, [ | ||
'apm', | ||
'infrastructure', | ||
'logs', | ||
'uptime', | ||
]); | ||
expect(Object.keys(browserFields)).to.eql(['base']); | ||
}); | ||
|
||
it(`${superUser.username} should be able to get browser fields for o11y featureIds`, async () => { | ||
const browserFields = await getBrowserFieldsByFeatureId(superUser, [ | ||
'apm', | ||
'infrastructure', | ||
'logs', | ||
'uptime', | ||
]); | ||
expect(Object.keys(browserFields)).to.eql(['base']); | ||
}); | ||
|
||
it(`${superUser.username} should NOT be able to get browser fields for siem featureId`, async () => { | ||
await getBrowserFieldsByFeatureId(superUser, ['siem'], 404); | ||
}); | ||
|
||
it(`${secOnlyRead.username} should NOT be able to get browser fields for siem featureId`, async () => { | ||
await getBrowserFieldsByFeatureId(secOnlyRead, ['siem'], 404); | ||
}); | ||
}); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters