Skip to content

Commit

Permalink
Merge branch '8.11' into backport/8.11/pr-170932
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Nov 10, 2023
2 parents 5506a02 + 09feaf4 commit 028c058
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -688,55 +688,108 @@ describe('tagKibanaAssets', () => {
);
});

it('should respect SecuritySolution tags', async () => {
savedObjectTagClient.get.mockRejectedValue(new Error('not found'));
savedObjectTagClient.create.mockImplementation(({ name }: { name: string }) =>
Promise.resolve({ id: name.toLowerCase(), name })
);
const kibanaAssets = {
dashboard: [
{ id: 'dashboard1', type: 'dashboard' },
{ id: 'dashboard2', type: 'dashboard' },
{ id: 'search_id1', type: 'search' },
{ id: 'search_id2', type: 'search' },
],
} as any;
const assetTags = [
{
text: 'Security Solution',
asset_types: ['dashboard'],
},
];
await tagKibanaAssets({
savedObjectTagAssignmentService,
savedObjectTagClient,
kibanaAssets,
pkgTitle: 'TestPackage',
pkgName: 'test-pkg',
spaceId: 'default',
importedAssets: [],
assetTags,
describe('Security Solution tag', () => {
it('creates tag in default space', async () => {
savedObjectTagClient.get.mockRejectedValue(new Error('not found'));
savedObjectTagClient.create.mockImplementation(({ name }: { name: string }) =>
Promise.resolve({ id: name.toLowerCase(), name })
);
const kibanaAssets = {
dashboard: [
{ id: 'dashboard1', type: 'dashboard' },
{ id: 'dashboard2', type: 'dashboard' },
{ id: 'search_id1', type: 'search' },
{ id: 'search_id2', type: 'search' },
],
} as any;
const assetTags = [
{
text: 'Security Solution',
asset_types: ['dashboard'],
},
];
await tagKibanaAssets({
savedObjectTagAssignmentService,
savedObjectTagClient,
kibanaAssets,
pkgTitle: 'TestPackage',
pkgName: 'test-pkg',
spaceId: 'default',
importedAssets: [],
assetTags,
});
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
managedTagPayloadArg1,
managedTagPayloadArg2
);
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
{
color: '#4DD2CA',
description: '',
name: 'TestPackage',
},
{ id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false }
);
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
{
color: expect.any(String),
description: 'Tag defined in package-spec',
name: 'Security Solution',
},
{ id: 'security-solution-default', overwrite: true, refresh: false }
);
});

it('creates tag in non-default space', async () => {
savedObjectTagClient.get.mockRejectedValue(new Error('not found'));
savedObjectTagClient.create.mockImplementation(({ name }: { name: string }) =>
Promise.resolve({ id: name.toLowerCase(), name })
);
const kibanaAssets = {
dashboard: [
{ id: 'dashboard1', type: 'dashboard' },
{ id: 'dashboard2', type: 'dashboard' },
{ id: 'search_id1', type: 'search' },
{ id: 'search_id2', type: 'search' },
],
} as any;
const assetTags = [
{
text: 'Security Solution',
asset_types: ['dashboard'],
},
];
await tagKibanaAssets({
savedObjectTagAssignmentService,
savedObjectTagClient,
kibanaAssets,
pkgTitle: 'TestPackage',
pkgName: 'test-pkg',
spaceId: 'my-secondary-space',
importedAssets: [],
assetTags,
});
expect(savedObjectTagClient.create).toHaveBeenCalledWith(managedTagPayloadArg1, {
...managedTagPayloadArg2,
id: 'fleet-managed-my-secondary-space',
});
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
{
color: expect.any(String),
description: '',
name: 'TestPackage',
},
{ id: 'fleet-pkg-test-pkg-my-secondary-space', overwrite: true, refresh: false }
);
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
{
color: expect.anything(),
description: 'Tag defined in package-spec',
name: 'Security Solution',
},
{ id: 'security-solution-my-secondary-space', overwrite: true, refresh: false }
);
});
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
managedTagPayloadArg1,
managedTagPayloadArg2
);
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
{
color: '#4DD2CA',
description: '',
name: 'TestPackage',
},
{ id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false }
);
expect(savedObjectTagClient.create).toHaveBeenCalledWith(
{
color: expect.any(String),
description: 'Tag defined in package-spec',
name: 'Security Solution',
},
{ id: 'security-solution-default', overwrite: true, refresh: false }
);
});

it('should only call savedObjectTagClient.create for basic tags if there are no assetTags to assign', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const PACKAGE_TAG_COLOR = '#4DD2CA';
const MANAGED_TAG_NAME = 'Managed';
const LEGACY_MANAGED_TAG_ID = 'managed';
const SECURITY_SOLUTION_TAG_NAME = 'Security Solution';
const SECURITY_SOLUTION_TAG_ID = 'security-solution-default';
const SECURITY_SOLUTION_TAG_ID_BASE = 'security-solution';

// the tag service only accepts 6-digits hex colors
const TAG_COLORS = [
Expand Down Expand Up @@ -65,8 +65,10 @@ const getLegacyPackageTagId = (pkgName: string) => pkgName;
In that case return id `security-solution-default`
*/
export const getPackageSpecTagId = (spaceId: string, pkgName: string, tagName: string) => {
if (tagName.toLowerCase() === SECURITY_SOLUTION_TAG_NAME.toLowerCase())
return SECURITY_SOLUTION_TAG_ID;
if (tagName.toLowerCase() === SECURITY_SOLUTION_TAG_NAME.toLowerCase()) {
return `${SECURITY_SOLUTION_TAG_ID_BASE}-${spaceId}`;
}

// UUID v5 needs a namespace (uuid.DNS) to generate a predictable uuid
const uniqueId = uuidv5(`${tagName.toLowerCase()}`, uuidv5.DNS);
return `fleet-shared-tag-${pkgName}-${uniqueId}-${spaceId}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

import * as t from 'io-ts';
import { toNumberRt } from '@kbn/io-ts-utils';
import { Direction } from '../../search_strategy';

export const getLiveQueryResultsRequestQuerySchema = t.type({
kuery: t.union([t.string, t.undefined]),
page: t.union([toNumberRt, t.undefined]),
pageSize: t.union([toNumberRt, t.undefined]),
sort: t.union([t.string, t.undefined]),
sortOrder: t.union([t.union([t.literal('asc'), t.literal('desc')]), t.undefined]),
sortOrder: t.union([t.literal(Direction.asc), t.literal(Direction.desc), t.undefined]),
});

export type GetLiveQueryResultsRequestQuerySchema = t.OutputOf<
Expand Down
49 changes: 49 additions & 0 deletions x-pack/plugins/osquery/cypress/e2e/api/live_query_results.cy.ts
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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { request } from '../../tasks/common';
import { loadLiveQuery } from '../../tasks/api_fixtures';
import { API_VERSIONS } from '../../../common/constants';
import { ServerlessRoleName } from '../../support/roles';

describe('Live query', { tags: ['@ess', '@serverless'] }, () => {
let liveQueryId: string;
let queriesQueryActionId: string;

beforeEach(() => {
cy.login(ServerlessRoleName.SOC_MANAGER);
loadLiveQuery().then((liveQuery) => {
liveQueryId = liveQuery.action_id;
queriesQueryActionId = liveQuery.queries?.[0].action_id;
});
});

context('GET getLiveQueryDetailsRoute', () => {
it('validates we get successful response', () => {
request({
url: `/api/osquery/live_queries/${liveQueryId}`,
headers: {
'Elastic-Api-Version': API_VERSIONS.public.v1,
},
}).then((response) => {
expect(response.status).to.eq(200);
});
});
});
context('GET getLiveQueryResultsRoute', () => {
it('validates we get successful response', () => {
request({
url: `/api/osquery/live_queries/${liveQueryId}/results/${queriesQueryActionId}`,
headers: {
'Elastic-Api-Version': API_VERSIONS.public.v1,
},
}).then((response) => {
expect(response.status).to.eq(200);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import { PLUGIN_ID } from '../../../common';
import type {
ActionDetailsRequestOptions,
ActionDetailsStrategyResponse,
ResultsRequestOptions,
ResultsStrategyResponse,
} from '../../../common/search_strategy';
import { OsqueryQueries } from '../../../common/search_strategy';
import { Direction, OsqueryQueries } from '../../../common/search_strategy';
import { generateTablePaginationOptions } from '../../../common/utils/build_query';
import { getActionResponses } from './utils';
import {
Expand Down Expand Up @@ -79,7 +81,7 @@ export const getLiveQueryResultsRoute = (router: IRouter<DataRequestHandlerConte
);

const res = await lastValueFrom(
search.search<{}>(
search.search<ResultsRequestOptions, ResultsStrategyResponse>(
{
actionId: request.params.actionId,
factoryQueryType: OsqueryQueries.results,
Expand All @@ -88,10 +90,12 @@ export const getLiveQueryResultsRoute = (router: IRouter<DataRequestHandlerConte
request.query.page ?? 0,
request.query.pageSize ?? 100
),
sort: {
direction: request.query.sortOrder ?? 'desc',
field: request.query.sort ?? '@timestamp',
},
sort: [
{
direction: request.query.sortOrder ?? Direction.desc,
field: request.query.sort ?? '@timestamp',
},
],
},
{ abortSignal, strategy: 'osquerySearchStrategy' }
)
Expand Down

0 comments on commit 028c058

Please sign in to comment.