forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Alerting] Export rules and connectors (elastic#98802)
* Adding importableAndExportable but hidden saved object types to saved object feature privilege * Adding helper function for transforming rule for export. Added audit logging * Adding helper function for transforming rule for export. Added audit logging * Adding unit test for transforming rules for export * Exporting connectors * Removing auditing during export * Adding import/export to docs * PR fixes * Using action type validation onExport * Fixing logic for connectors with optional secrets * Fixing logic for connectors with optional secrets Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
- Loading branch information
1 parent
9f9c417
commit 909fa63
Showing
11 changed files
with
495 additions
and
7 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
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
253 changes: 253 additions & 0 deletions
253
x-pack/plugins/actions/server/saved_objects/transform_connectors_for_export.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,253 @@ | ||
/* | ||
* 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 { transformConnectorsForExport } from './transform_connectors_for_export'; | ||
import { ActionTypeRegistry, ActionTypeRegistryOpts } from '../action_type_registry'; | ||
import { loggingSystemMock } from '../../../../../src/core/server/mocks'; | ||
import { actionsConfigMock } from '../actions_config.mock'; | ||
import { licensingMock } from '../../../licensing/server/mocks'; | ||
import { licenseStateMock } from '../lib/license_state.mock'; | ||
import { taskManagerMock } from '../../../task_manager/server/mocks'; | ||
import { ActionExecutor, TaskRunnerFactory } from '../lib'; | ||
import { registerBuiltInActionTypes } from '../builtin_action_types'; | ||
|
||
describe('transform connector for export', () => { | ||
const actionTypeRegistryParams: ActionTypeRegistryOpts = { | ||
licensing: licensingMock.createSetup(), | ||
taskManager: taskManagerMock.createSetup(), | ||
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })), | ||
actionsConfigUtils: actionsConfigMock.create(), | ||
licenseState: licenseStateMock.create(), | ||
preconfiguredActions: [], | ||
}; | ||
const actionTypeRegistry: ActionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams); | ||
|
||
registerBuiltInActionTypes({ | ||
logger: loggingSystemMock.create().get(), | ||
actionTypeRegistry, | ||
actionsConfigUtils: actionsConfigMock.create(), | ||
}); | ||
|
||
const connectorsWithNoSecrets = [ | ||
{ | ||
id: '1', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.email', | ||
name: 'email connector without auth', | ||
isMissingSecrets: false, | ||
config: { | ||
hasAuth: false, | ||
from: 'me@me.com', | ||
host: 'host', | ||
port: 22, | ||
service: null, | ||
secure: null, | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '2', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.index', | ||
name: 'index connector', | ||
isMissingSecrets: false, | ||
config: { | ||
index: 'test-index', | ||
refresh: false, | ||
executionTimeField: null, | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '3', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.server-log', | ||
name: 'server log connector', | ||
isMissingSecrets: false, | ||
config: {}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '4', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.webhook', | ||
name: 'webhook connector without auth', | ||
isMissingSecrets: false, | ||
config: { | ||
method: 'post', | ||
hasAuth: false, | ||
url: 'https://webhook', | ||
headers: {}, | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
]; | ||
const connectorsWithSecrets = [ | ||
{ | ||
id: '1', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.email', | ||
name: 'email connector with auth', | ||
isMissingSecrets: false, | ||
config: { | ||
hasAuth: true, | ||
from: 'me@me.com', | ||
host: 'host', | ||
port: 22, | ||
service: null, | ||
secure: null, | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '2', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.resilient', | ||
name: 'resilient connector', | ||
isMissingSecrets: false, | ||
config: { | ||
apiUrl: 'https://resilient', | ||
orgId: 'origId', | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '3', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.servicenow', | ||
name: 'servicenow itsm connector', | ||
isMissingSecrets: false, | ||
config: { | ||
apiUrl: 'https://servicenow', | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '4', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.pagerduty', | ||
name: 'pagerduty connector', | ||
isMissingSecrets: false, | ||
config: { | ||
apiUrl: 'https://pagerduty', | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '5', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.jira', | ||
name: 'jira connector', | ||
isMissingSecrets: false, | ||
config: { | ||
apiUrl: 'https://jira', | ||
projectKey: 'foo', | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '6', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.teams', | ||
name: 'teams connector', | ||
isMissingSecrets: false, | ||
config: {}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '7', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.slack', | ||
name: 'slack connector', | ||
isMissingSecrets: false, | ||
config: {}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '8', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.servicenow-sir', | ||
name: 'servicenow sir connector', | ||
isMissingSecrets: false, | ||
config: { | ||
apiUrl: 'https://servicenow-sir', | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
{ | ||
id: '8', | ||
type: 'action', | ||
attributes: { | ||
actionTypeId: '.webhook', | ||
name: 'webhook connector with auth', | ||
isMissingSecrets: false, | ||
config: { | ||
method: 'post', | ||
hasAuth: true, | ||
url: 'https://webhook', | ||
headers: {}, | ||
}, | ||
secrets: 'asbqw4tqbef', | ||
}, | ||
references: [], | ||
}, | ||
]; | ||
|
||
it('should not change connectors without secrets', () => { | ||
expect(transformConnectorsForExport(connectorsWithNoSecrets, actionTypeRegistry)).toEqual( | ||
connectorsWithNoSecrets | ||
); | ||
}); | ||
|
||
it('should remove secrets for connectors with secrets', () => { | ||
expect(transformConnectorsForExport(connectorsWithSecrets, actionTypeRegistry)).toEqual( | ||
connectorsWithSecrets.map((connector) => ({ | ||
...connector, | ||
attributes: { | ||
...connector.attributes, | ||
isMissingSecrets: true, | ||
}, | ||
})) | ||
); | ||
}); | ||
}); |
50 changes: 50 additions & 0 deletions
50
x-pack/plugins/actions/server/saved_objects/transform_connectors_for_export.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,50 @@ | ||
/* | ||
* 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 { SavedObject } from 'kibana/server'; | ||
import { ActionTypeRegistry } from '../action_type_registry'; | ||
import { validateSecrets } from '../lib'; | ||
import { RawAction, ActionType } from '../types'; | ||
|
||
export function transformConnectorsForExport( | ||
connectors: SavedObject[], | ||
actionTypeRegistry: ActionTypeRegistry | ||
): Array<SavedObject<RawAction>> { | ||
return connectors.map((c) => { | ||
const connector = c as SavedObject<RawAction>; | ||
return transformConnectorForExport( | ||
connector, | ||
actionTypeRegistry.get(connector.attributes.actionTypeId) | ||
); | ||
}); | ||
} | ||
|
||
function transformConnectorForExport( | ||
connector: SavedObject<RawAction>, | ||
actionType: ActionType | ||
): SavedObject<RawAction> { | ||
let isMissingSecrets = false; | ||
try { | ||
// If connector requires secrets, this will throw an error | ||
validateSecrets(actionType, {}); | ||
|
||
// If connector has optional (or no) secrets, set isMissingSecrets value to value of hasAuth | ||
// If connector doesn't have hasAuth value, default to isMissingSecrets: false | ||
isMissingSecrets = (connector?.attributes?.config?.hasAuth as boolean) ?? false; | ||
} catch (err) { | ||
isMissingSecrets = true; | ||
} | ||
|
||
// Skip connectors | ||
return { | ||
...connector, | ||
attributes: { | ||
...connector.attributes, | ||
isMissingSecrets, | ||
}, | ||
}; | ||
} |
Oops, something went wrong.