Skip to content

Commit

Permalink
Merge branch 'main' into connector-scheduling-cron-first
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Nov 28, 2022
2 parents 34d34aa + a270d75 commit f52eebc
Show file tree
Hide file tree
Showing 23 changed files with 389 additions and 190 deletions.
2 changes: 1 addition & 1 deletion docs/maps/connect-to-ems.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ endif::[]

| `ssl.supportedProtocols`
| An array of supported protocols with versions.
Valid protocols: `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. *Default: `TLSv1.1`, `TLSv1.2`, `TLSv1.3`*. <<server-ssl-supportedProtocols,Equivalent {kib} setting>>.
Valid protocols: `TLSv1`, `TLSv1.1`, `TLSv1.2`. *Default: `TLSv1.1`, `TLSv1.2`*. <<server-ssl-supportedProtocols,Equivalent {kib} setting>>.

| `ssl.cipherSuites`
| Details on the format, and the valid options, are available via the
Expand Down
2 changes: 1 addition & 1 deletion packages/shared-ux/file/image/impl/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ date: 2022-11-22

## Description

A light wrapper around <EuiImage /> that introduces some "file-aware" functionality like displaying a [blurhash](https://blurha.sh/) before the final image loads.
A light wrapper around [EuiImage](https://elastic.github.io/eui/#/display/image) that introduces some "file-aware" functionality like displaying a [blurhash](https://blurha.sh/) before the final image loads.

## Lazy loading

Expand Down
9 changes: 8 additions & 1 deletion src/plugins/guided_onboarding/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ import { GuideState } from '@kbn/guided-onboarding';
* complete: at least one guide has been completed
* quit: the user quit a guide before completion
* skipped: the user skipped on the landing page
* error: unable to retrieve the plugin state from saved objects
*/
export type PluginStatus = 'not_started' | 'in_progress' | 'complete' | 'quit' | 'skipped';
export type PluginStatus =
| 'not_started'
| 'in_progress'
| 'complete'
| 'quit'
| 'skipped'
| 'error';

export interface PluginState {
status: PluginStatus;
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/guided_onboarding/public/services/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ describe('GuidedOnboarding ApiService', () => {
expect(httpClient.get).toHaveBeenCalledTimes(1);
});

it(`re-sends the request if the previous one failed`, async () => {
it(`doesn't send multiple requests if the request failed`, async () => {
httpClient.get.mockRejectedValueOnce(new Error('request failed'));
subscription = apiService.fetchPluginState$().subscribe();
// wait until the request fails
await new Promise((resolve) => process.nextTick(resolve));
anotherSubscription = apiService.fetchPluginState$().subscribe();
expect(httpClient.get).toHaveBeenCalledTimes(2);
expect(httpClient.get).toHaveBeenCalledTimes(1);
});

it(`re-sends the request if the subscription was unsubscribed before the request completed`, async () => {
Expand Down
8 changes: 7 additions & 1 deletion src/plugins/guided_onboarding/public/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ export class ApiService implements GuidedOnboardingApi {
})
.catch((error) => {
this.isPluginStateLoading = false;
observer.error(error);
// if the request fails, we initialize the state with error
observer.next({ status: 'error', isActivePeriod: false });
this.pluginState$.next({
status: 'error',
isActivePeriod: false,
});
observer.complete();
});
return () => {
this.isPluginStateLoading = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,7 @@ export const getPluginState = async (savedObjectsClient: SavedObjectsClient) =>
return pluginState;
} else {
// create a SO to keep track of the correct creation date
try {
await updatePluginStatus(savedObjectsClient, 'not_started');
// @yulia, we need to add a user permissions
// check here instead of swallowing this error
// see issue: https://github.com/elastic/kibana/issues/145434
// eslint-disable-next-line no-empty
} catch (e) {}

await updatePluginStatus(savedObjectsClient, 'not_started');
return {
status: 'not_started',
isActivePeriod: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ import { compact, debounce, isEmpty, isEqual, isFunction, partition } from 'loda
import { CoreStart, DocLinksStart, Toast } from '@kbn/core/public';
import type { Query } from '@kbn/es-query';
import { DataPublicPluginStart, getQueryLog } from '@kbn/data-plugin/public';
import {
type DataView,
DataView as KibanaDataView,
DataViewsPublicPluginStart,
} from '@kbn/data-views-plugin/public';
import { type DataView, DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import type { PersistedLog } from '@kbn/data-plugin/public';
import { getFieldSubtypeNested, KIBANA_USER_QUERY_LANGUAGE_KEY } from '@kbn/data-plugin/common';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
Expand Down Expand Up @@ -188,7 +184,7 @@ export default class QueryStringInputUI extends PureComponent<QueryStringInputPr
QueryStringInputProps['indexPatterns'][number],
DataView
>(this.props.indexPatterns || [], (indexPattern): indexPattern is DataView => {
return indexPattern instanceof KibanaDataView;
return indexPattern.hasOwnProperty('fields') && indexPattern.hasOwnProperty('title');
});
const idOrTitlePatterns = stringPatterns.map((sp) =>
typeof sp === 'string' ? { type: 'title', value: sp } : sp
Expand Down
78 changes: 77 additions & 1 deletion x-pack/plugins/fleet/server/routes/security.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { createAppContextStartContractMock } from '../mocks';
import { appContextService } from '../services';
import type { FleetRequestHandlerContext } from '../types';

import { makeRouterWithFleetAuthz } from './security';
import { deserializeAuthzConfig, makeRouterWithFleetAuthz, serializeAuthzConfig } from './security';

function getCheckPrivilegesMockedImplementation(kibanaRoles: string[]) {
return (checkPrivileges: CheckPrivilegesPayload) => {
Expand Down Expand Up @@ -198,3 +198,79 @@ describe('FleetAuthzRouter', () => {
});
});
});

describe('serializeAuthzConfig', () => {
it('should serialize authz to tags', () => {
const res = serializeAuthzConfig({
fleetAuthz: {
fleet: {
readEnrollmentTokens: true,
setup: true,
},
integrations: {
readPackageInfo: true,
removePackages: true,
},
packagePrivileges: {
endpoint: {
actions: {
readPolicyManagement: {
executePackageAction: true,
},
readBlocklist: {
executePackageAction: true,
},
},
},
},
},
});

expect(res).toEqual([
'fleet:authz:fleet:readEnrollmentTokens',
'fleet:authz:fleet:setup',
'fleet:authz:integrations:readPackageInfo',
'fleet:authz:integrations:removePackages',
'fleet:authz:packagePrivileges:endpoint:actions:readPolicyManagement:executePackageAction',
'fleet:authz:packagePrivileges:endpoint:actions:readBlocklist:executePackageAction',
]);
});
});

describe('deserializeAuthzConfig', () => {
it('should deserialize tags to fleet authz', () => {
const res = deserializeAuthzConfig([
'fleet:authz:fleet:readEnrollmentTokens',
'fleet:authz:fleet:setup',
'fleet:authz:integrations:readPackageInfo',
'fleet:authz:integrations:removePackages',
'fleet:authz:packagePrivileges:endpoint:actions:readPolicyManagement:executePackageAction',
'fleet:authz:packagePrivileges:endpoint:actions:readBlocklist:executePackageAction',
]);

expect(res).toEqual({
fleetAuthz: {
fleet: {
readEnrollmentTokens: true,
setup: true,
},
integrations: {
readPackageInfo: true,
removePackages: true,
},
packagePrivileges: {
endpoint: {
actions: {
readPolicyManagement: {
executePackageAction: true,
},
readBlocklist: {
executePackageAction: true,
},
},
},
},
},
});
});
});
11 changes: 7 additions & 4 deletions x-pack/plugins/fleet/server/routes/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ function shouldHandlePostAuthRequest(req: KibanaRequest) {
}
return false;
}
function deserializeAuthzConfig(tags: readonly string[]): FleetAuthzRouteConfig {
// Exported for test only
export function deserializeAuthzConfig(tags: readonly string[]): FleetAuthzRouteConfig {
let fleetAuthz: FleetAuthzRequirements | undefined;
for (const tag of tags) {
if (!tag.match(/^fleet:authz/)) {
Expand All @@ -199,7 +200,7 @@ function deserializeAuthzConfig(tags: readonly string[]): FleetAuthzRouteConfig
.replace(/^fleet:authz:/, '')
.split(':')
.reduce((acc: any, key, idx, keys) => {
if (idx === keys.length + 1) {
if (idx === keys.length - 1) {
acc[key] = true;

return acc;
Expand All @@ -215,7 +216,9 @@ function deserializeAuthzConfig(tags: readonly string[]): FleetAuthzRouteConfig

return { fleetAuthz };
}
function serializeAuthzConfig(config: FleetAuthzRouteConfig): string[] {

// Exported for test only
export function serializeAuthzConfig(config: FleetAuthzRouteConfig): string[] {
const tags: string[] = [];

if (config.fleetAuthz) {
Expand All @@ -224,7 +227,7 @@ function serializeAuthzConfig(config: FleetAuthzRouteConfig): string[] {
if (typeof requirements[key] === 'boolean') {
tags.push(`fleet:authz:${prefix}${key}`);
} else if (typeof requirements[key] !== 'undefined') {
fleetAuthzToTags(requirements[key] as DeepPartialTruthy<Authz>, `${key}:`);
fleetAuthzToTags(requirements[key] as DeepPartialTruthy<Authz>, `${prefix}${key}:`);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@
*/

import { login, visit } from '../../tasks/login';
import { openAddFilterPopover, fillAddFilterForm } from '../../tasks/search_bar';
import { GLOBAL_SEARCH_BAR_FILTER_ITEM } from '../../screens/search_bar';
import {
openAddFilterPopover,
fillAddFilterForm,
openKqlQueryBar,
fillKqlQueryBar,
} from '../../tasks/search_bar';
import {
AUTO_SUGGEST_AGENT_NAME,
AUTO_SUGGEST_HOST_NAME_VALUE,
GLOBAL_SEARCH_BAR_FILTER_ITEM,
} from '../../screens/search_bar';
import { getHostIpFilter } from '../../objects/filter';

import { HOSTS_URL } from '../../urls/navigation';
Expand All @@ -29,4 +38,11 @@ describe('SearchBar', () => {
`${getHostIpFilter().key}: ${getHostIpFilter().value}`
);
});

it('auto suggests fields from the data view and auto completes available field values', () => {
openKqlQueryBar();
cy.get(AUTO_SUGGEST_AGENT_NAME).should('be.visible');
fillKqlQueryBar(`host.name:`);
cy.get(AUTO_SUGGEST_HOST_NAME_VALUE).should('be.visible');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@ export const GLOBAL_SEARCH_BAR_FILTER_ITEM = '#popoverFor_filter0';
export const GLOBAL_SEARCH_BAR_FILTER_ITEM_AT = (value: number) => `#popoverFor_filter${value}`;

export const GLOBAL_SEARCH_BAR_PINNED_FILTER = '.globalFilterItem-isPinned';

export const GLOBAL_KQL_INPUT =
'[data-test-subj="filters-global-container"] [data-test-subj="unifiedQueryInput"] textarea';

export const AUTO_SUGGEST_AGENT_NAME = `[data-test-subj="autocompleteSuggestion-field-agent.name-"]`;

export const AUTO_SUGGEST_HOST_NAME_VALUE = `[data-test-subj='autocompleteSuggestion-value-"siem-kibana"-']`;
11 changes: 11 additions & 0 deletions x-pack/plugins/security_solution/cypress/tasks/search_bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
ADD_FILTER_FORM_OPERATOR_FIELD,
ADD_FILTER_FORM_FIELD_OPTION,
ADD_FILTER_FORM_FILTER_VALUE_INPUT,
GLOBAL_KQL_INPUT,
} from '../screens/search_bar';

export const openAddFilterPopover = () => {
Expand All @@ -24,6 +25,16 @@ export const openAddFilterPopover = () => {
cy.get(GLOBAL_SEARCH_BAR_ADD_FILTER).click();
};

export const openKqlQueryBar = () => {
cy.get(GLOBAL_KQL_INPUT).should('be.visible');
cy.get(GLOBAL_KQL_INPUT).click();
};

export const fillKqlQueryBar = (query: string) => {
cy.get(GLOBAL_KQL_INPUT).should('be.visible');
cy.get(GLOBAL_KQL_INPUT).type(query);
};

export const fillAddFilterForm = ({ key, value, operator }: SearchBarFilter) => {
cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('exist');
cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('be.visible');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import sinon from 'sinon';
import moment from 'moment';
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';

import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import type { Filter } from '@kbn/es-query';
Expand All @@ -16,6 +18,7 @@ import {
sendAlertToTimelineAction,
sendBulkEventsToTimelineAction,
determineToAndFrom,
getNewTermsData,
} from './actions';
import {
defaultTimelineProps,
Expand Down Expand Up @@ -933,6 +936,63 @@ describe('alert actions', () => {
});
});

describe('New terms', () => {
describe('getNewTermsData', () => {
it('should return new terms data correctly for single value field', () => {
const newTermsEcsMock = cloneDeep(ecsDataMockWithNoTemplateTimeline[0]);
set(newTermsEcsMock, 'kibana.alert.new_terms', ['host-0']);
set(newTermsEcsMock, 'kibana.alert.rule.parameters.new_terms_fields', ['host.name']);

expect(getNewTermsData(newTermsEcsMock).dataProviders).toEqual([
{
and: [],
enabled: true,
excluded: false,
id: 'send-alert-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-host-name-host-0',
kqlQuery: '',
name: 'host.name',
queryMatch: { field: 'host.name', operator: ':', value: 'host-0' },
},
]);
});

it('should return new terms data as AND query for multiple values field', () => {
const newTermsEcsMock = cloneDeep(ecsDataMockWithNoTemplateTimeline[0]);
set(newTermsEcsMock, 'kibana.alert.new_terms', ['host-0', '127.0.0.1']);
set(newTermsEcsMock, 'kibana.alert.rule.parameters.new_terms_fields', [
'host.name',
'host.ip',
]);

expect(getNewTermsData(newTermsEcsMock).dataProviders).toEqual([
{
and: [
{
and: [],
enabled: true,
excluded: false,
id: 'send-alert-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-host-ip-127.0.0.1',
kqlQuery: '',
name: 'host.ip',
queryMatch: {
field: 'host.ip',
operator: ':',
value: '127.0.0.1',
},
},
],
enabled: true,
excluded: false,
id: 'send-alert-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-host-name-host-0',
kqlQuery: '',
name: 'host.name',
queryMatch: { field: 'host.name', operator: ':', value: 'host-0' },
},
]);
});
});
});

describe('determineToAndFrom', () => {
beforeEach(() => {
fetchMock.mockResolvedValue({
Expand Down
Loading

0 comments on commit f52eebc

Please sign in to comment.