Skip to content

Commit

Permalink
Merge branch '7.8' into 7.8-move-files
Browse files Browse the repository at this point in the history
  • Loading branch information
elasticmachine authored May 7, 2020
2 parents c2af1bf + 667406a commit e82b236
Show file tree
Hide file tree
Showing 21 changed files with 335 additions and 190 deletions.
7 changes: 7 additions & 0 deletions docs/migration/migrate_7_2.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ your application to Kibana 7.2.

See also <<release-highlights-7.2.0, release highlights>> and <<release-notes-7.2.0, release notes>>.

//NOTE: The notable-breaking-changes tagged regions are re-used in the
//Installation and Upgrade Guide

//tag::notable-breaking-changes[]

// end::notable-breaking-changes[]

[float]
[[breaking_72_index_pattern_changes]]

Expand Down
1 change: 1 addition & 0 deletions docs/migration/migrate_7_5.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ Any installs that previously enabled the Code app will now log a warning when
Kibana starts up. It's safe to remove all configurations starting with
`xpack.code.`. Starting in 8.0, these warnings will become errors that prevent
Kibana from starting up.
// end::notable-breaking-changes[]
5 changes: 5 additions & 0 deletions docs/migration/migrate_7_6.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ your application to Kibana 7.6.
* <<user-facing-changes, Breaking changes for users>>
* <<general-plugin-API-changes, Breaking changes for plugin developers>>

// The following section is re-used in the Installation and Upgrade Guide
//tag::notable-breaking-changes[]

// end::notable-breaking-changes[]

[float]
[[user-facing-changes]]
=== Breaking changes for users
Expand Down
12 changes: 4 additions & 8 deletions docs/migration/migrate_7_7.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@
This page discusses the breaking changes that you need to be aware of when migrating
your application to Kibana 7.7.

//NOTE: The notable-breaking-changes tagged regions are re-used in the
//Installation and Upgrade Guide

////
The following section is re-used in the Installation and Upgrade Guide
[[breaking_70_notable]]
=== Notable breaking changes
////
// The following section is re-used in the Installation and Upgrade Guide
// tag::notable-breaking-changes[]

// end::notable-breaking-changes[]

[float]
=== Breaking changes for users
Expand Down
6 changes: 3 additions & 3 deletions docs/user/alerting/pre-configured-connectors.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ The following example shows a valid configuration 2 out-of-the box connector.

```js
xpack.actions.preconfigured:
- id: 'my-slack1' <1>
my-slack1: <1>
actionTypeId: .slack <2>
name: 'Slack #xyz' <3>
config: <4>
webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz'
- id: 'webhook-service'
webhook-service:
actionTypeId: .webhook
name: 'Email service'
config:
Expand All @@ -41,7 +41,7 @@ The following example shows a valid configuration 2 out-of-the box connector.
password: changeme
```

<1> `id` is the action connector identifier.
<1> the key is the action connector identifier, eg `my-slack1` in this example.
<2> `actionTypeId` is the action type identifier.
<3> `name` is the name of the preconfigured connector.
<4> `config` is the action type specific to the configuration.
Expand Down
2 changes: 1 addition & 1 deletion test/functional/apps/discover/_discover_histogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function({ getService, getPageObjects }) {
describe('discover histogram', function describeIndexTests() {
before(async function() {
log.debug('load kibana index with default index pattern');
await PageObjects.common.navigateToApp('home');
await PageObjects.common.navigateToApp('settings');
await security.testUser.setRoles([
'kibana_admin',
'test_logstash_reader',
Expand Down
1 change: 1 addition & 0 deletions test/functional/apps/getting_started/_shakespeare.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export default function({ getService, getPageObjects }) {
});

it('should create shakespeare index pattern', async function() {
await PageObjects.common.navigateToApp('settings');
log.debug('Create shakespeare index pattern');
await PageObjects.settings.createIndexPattern('shakespeare', null);
const patternName = await PageObjects.settings.getIndexPageHeading();
Expand Down
4 changes: 2 additions & 2 deletions test/functional/page_objects/common_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
await browser.get(appUrl);
} else {
log.debug(`navigateToUrl ${appUrl}`);
await browser.get(appUrl);
await browser.get(appUrl, insertTimestamp);
// accept alert if it pops up
const alert = await browser.getAlert();
await alert?.accept();
Expand Down Expand Up @@ -242,7 +242,7 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
let lastUrl = await retry.try(async () => {
// since we're using hash URLs, always reload first to force re-render
log.debug('navigate to: ' + appUrl);
await browser.get(appUrl);
await browser.get(appUrl, insertTimestamp);
// accept alert if it pops up
const alert = await browser.getAlert();
await alert?.accept();
Expand Down
1 change: 0 additions & 1 deletion test/functional/page_objects/settings_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,6 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider
isStandardIndexPattern = true
) {
await retry.try(async () => {
await this.navigateTo();
await PageObjects.header.waitUntilLoadingHasFinished();
await this.clickKibanaIndexPatterns();
await PageObjects.header.waitUntilLoadingHasFinished();
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Built-In-Actions are configured using the _xpack.actions_ namespoace under _kiba
| _xpack.actions._**enabled** | Feature toggle which enabled Actions in Kibana. | boolean |
| _xpack.actions._**whitelistedHosts** | Which _hostnames_ are whitelisted for the Built-In-Action? This list should contain hostnames of every external service you wish to interact with using Webhooks, Email or any other built in Action. Note that you may use the string "\*" in place of a specific hostname to enable Kibana to target any URL, but keep in mind the potential use of such a feature to execute [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) attacks from your server. | Array<String> |
| _xpack.actions._**enabledActionTypes** | A list of _actionTypes_ id's that are enabled. A "\*" may be used as an element to indicate all registered actionTypes should be enabled. The actionTypes registered for Kibana are `.server-log`, `.slack`, `.email`, `.index`, `.pagerduty`, `.webhook`. Default: `["*"]` | Array<String> |
| _xpack.actions._**preconfigured** | A list of preconfigured actions. Default: `[]` | Array<Object> |
| _xpack.actions._**preconfigured** | A object of action id / preconfigured actions. Default: `{}` | Array<Object> |

#### Whitelisting Built-in Action Types

Expand Down
53 changes: 44 additions & 9 deletions x-pack/plugins/actions/server/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('config validation', () => {
"enabledActionTypes": Array [
"*",
],
"preconfigured": Array [],
"preconfigured": Object {},
"whitelistedHosts": Array [
"*",
],
Expand All @@ -24,38 +24,73 @@ describe('config validation', () => {

test('action with preconfigured actions', () => {
const config: Record<string, unknown> = {
preconfigured: [
{
id: 'my-slack1',
preconfigured: {
mySlack1: {
actionTypeId: '.slack',
name: 'Slack #xyz',
config: {
webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz',
},
},
],
},
};
expect(configSchema.validate(config)).toMatchInlineSnapshot(`
Object {
"enabled": true,
"enabledActionTypes": Array [
"*",
],
"preconfigured": Array [
Object {
"preconfigured": Object {
"mySlack1": Object {
"actionTypeId": ".slack",
"config": Object {
"webhookUrl": "https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz",
},
"id": "my-slack1",
"name": "Slack #xyz",
"secrets": Object {},
},
],
},
"whitelistedHosts": Array [
"*",
],
}
`);
});

test('validates preconfigured action ids', () => {
expect(() =>
configSchema.validate(preConfiguredActionConfig(''))
).toThrowErrorMatchingInlineSnapshot(
`"[preconfigured]: invalid preconfigured action id \\"\\""`
);

expect(() =>
configSchema.validate(preConfiguredActionConfig('constructor'))
).toThrowErrorMatchingInlineSnapshot(
`"[preconfigured]: invalid preconfigured action id \\"constructor\\""`
);

expect(() =>
configSchema.validate(preConfiguredActionConfig('__proto__'))
).toThrowErrorMatchingInlineSnapshot(
`"[preconfigured]: invalid preconfigured action id \\"__proto__\\""`
);
});
});

// object creator that ensures we can create a property named __proto__ on an
// object, via JSON.parse()
function preConfiguredActionConfig(id: string) {
return JSON.parse(`{
"preconfigured": {
${JSON.stringify(id)}: {
"actionTypeId": ".server-log",
"name": "server log 1"
},
"serverLog": {
"actionTypeId": ".server-log",
"name": "server log 2"
}
}
}`);
}
39 changes: 27 additions & 12 deletions x-pack/plugins/actions/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
import { schema, TypeOf } from '@kbn/config-schema';
import { WhitelistedHosts, EnabledActionTypes } from './actions_config';

const preconfiguredActionSchema = schema.object({
name: schema.string({ minLength: 1 }),
actionTypeId: schema.string({ minLength: 1 }),
config: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }),
secrets: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }),
});

export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
whitelistedHosts: schema.arrayOf(
Expand All @@ -21,18 +28,26 @@ export const configSchema = schema.object({
defaultValue: [WhitelistedHosts.Any],
}
),
preconfigured: schema.arrayOf(
schema.object({
id: schema.string({ minLength: 1 }),
name: schema.string(),
actionTypeId: schema.string({ minLength: 1 }),
config: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }),
secrets: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }),
}),
{
defaultValue: [],
}
),
preconfigured: schema.recordOf(schema.string(), preconfiguredActionSchema, {
defaultValue: {},
validate: validatePreconfigured,
}),
});

export type ActionsConfig = TypeOf<typeof configSchema>;

const invalidActionIds = new Set(['', '__proto__', 'constructor']);

function validatePreconfigured(preconfigured: Record<string, unknown>): string | undefined {
// check for ids that should not be used
for (const id of Object.keys(preconfigured)) {
if (invalidActionIds.has(id)) {
return `invalid preconfigured action id "${id}"`;
}
}

// in case __proto__ was used as a preconfigured action id ...
if (Object.getPrototypeOf(preconfigured) !== Object.getPrototypeOf({})) {
return `invalid preconfigured action id "__proto__"`;
}
}
57 changes: 28 additions & 29 deletions x-pack/plugins/actions/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { taskManagerMock } from '../../task_manager/server/mocks';
import { eventLogMock } from '../../event_log/server/mocks';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { ActionType } from './types';
import { ActionsConfig } from './config';
import {
ActionsPlugin,
ActionsPluginsSetup,
Expand All @@ -31,33 +32,11 @@ describe('Actions Plugin', () => {
let pluginsSetup: jest.Mocked<ActionsPluginsSetup>;

beforeEach(() => {
context = coreMock.createPluginInitializerContext({
preconfigured: [
{
id: 'my-slack1',
actionTypeId: '.slack',
name: 'Slack #xyz',
description: 'Send a message to the #xyz channel',
config: {
webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz',
},
},
{
id: 'custom-system-abc-connector',
actionTypeId: 'system-abc-action-type',
description: 'Send a notification to system ABC',
name: 'System ABC',
config: {
xyzConfig1: 'value1',
xyzConfig2: 'value2',
listOfThings: ['a', 'b', 'c', 'd'],
},
secrets: {
xyzSecret1: 'credential1',
xyzSecret2: 'credential2',
},
},
],
context = coreMock.createPluginInitializerContext<ActionsConfig>({
enabled: true,
enabledActionTypes: ['*'],
whitelistedHosts: ['*'],
preconfigured: {},
});
plugin = new ActionsPlugin(context);
coreSetup = coreMock.createSetup();
Expand Down Expand Up @@ -192,6 +171,7 @@ describe('Actions Plugin', () => {
});
});
});

describe('start()', () => {
let plugin: ActionsPlugin;
let coreSetup: ReturnType<typeof coreMock.createSetup>;
Expand All @@ -200,8 +180,18 @@ describe('Actions Plugin', () => {
let pluginsStart: jest.Mocked<ActionsPluginsStart>;

beforeEach(() => {
const context = coreMock.createPluginInitializerContext({
preconfigured: [],
const context = coreMock.createPluginInitializerContext<ActionsConfig>({
enabled: true,
enabledActionTypes: ['*'],
whitelistedHosts: ['*'],
preconfigured: {
preconfiguredServerLog: {
actionTypeId: '.server-log',
name: 'preconfigured-server-log',
config: {},
secrets: {},
},
},
});
plugin = new ActionsPlugin(context);
coreSetup = coreMock.createSetup();
Expand All @@ -220,6 +210,15 @@ describe('Actions Plugin', () => {
});

describe('getActionsClientWithRequest()', () => {
it('should handle preconfigured actions', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await plugin.setup(coreSetup as any, pluginsSetup);
const pluginStart = plugin.start(coreStart, pluginsStart);

expect(pluginStart.isActionExecutable('preconfiguredServerLog', '.server-log')).toBe(true);
});

it('should not throw error when ESO plugin not using a generated key', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
14 changes: 8 additions & 6 deletions x-pack/plugins/actions/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,14 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
const actionsConfig = (await this.config) as ActionsConfig;
const actionsConfigUtils = getActionsConfigurationUtilities(actionsConfig);

this.preconfiguredActions.push(
...actionsConfig.preconfigured.map(
preconfiguredAction =>
({ ...preconfiguredAction, isPreconfigured: true } as PreConfiguredAction)
)
);
for (const preconfiguredId of Object.keys(actionsConfig.preconfigured)) {
this.preconfiguredActions.push({
...actionsConfig.preconfigured[preconfiguredId],
id: preconfiguredId,
isPreconfigured: true,
});
}

const actionTypeRegistry = new ActionTypeRegistry({
taskRunnerFactory,
taskManager: plugins.taskManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export const ExpressionChart: React.FC<Props> = ({
/>
</>
) : null}
{isAbove ? (
{isAbove && first(expression.threshold) != null ? (
<RectAnnotation
id="upper-threshold"
style={{
Expand Down
Loading

0 comments on commit e82b236

Please sign in to comment.