[Connectors][API] Updated connectors with isMissingSecrets flag (#98223)

* [Connectors][API] Updated connectors with enabledAfterImport flag

* fixed functional tests

* added new field to connectors API docs

* added update unit test

* fixed test

* renamed enableAfterImport to isMissingSecrets

* removed onExport

* revert the logic of true/false for isMissingSecrets

* fixed test

* fixed tests

* added unit test

* fixed docs

* fixed import text and button labels

* fixed import text

* fixed text
This commit is contained in:
Yuliia Naumenko 2021-04-27 14:14:01 -07:00 committed by GitHub
parent 1a1c36a99b
commit 33f47ba590
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 362 additions and 20 deletions

View file

@ -73,6 +73,7 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"is_preconfigured": false
"is_preconfigured": false,
"is_missing_secrets": false
}
--------------------------------------------------

View file

@ -50,6 +50,7 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"is_preconfigured": false
"is_preconfigured": false,
"is_missing_secrets": false
}
--------------------------------------------------

View file

@ -56,6 +56,7 @@ The API returns the following:
"executionTimeField": null
},
"is_preconfigured": false,
"is_missing_secrets": false,
"referenced_by_count": 3
}
]

View file

@ -75,6 +75,7 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"isPreconfigured": false
"isPreconfigured": false,
"isMissingSecrets": false
}
--------------------------------------------------

View file

@ -52,6 +52,7 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"isPreconfigured": false
"isPreconfigured": false,
"isMissingSecrets": false
}
--------------------------------------------------

View file

@ -56,7 +56,8 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"isPreconfigured": false
"isPreconfigured": false,
"isMissingSecrets": false
}
]
--------------------------------------------------

View file

@ -70,6 +70,7 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"isPreconfigured": false
"isPreconfigured": false,
"isMissingSecrets": false
}
--------------------------------------------------

View file

@ -68,6 +68,7 @@ The API returns the following:
"refresh": false,
"executionTimeField": null
},
"is_preconfigured": false
"is_preconfigured": false,
"is_missing_secrets": false
}
--------------------------------------------------

View file

@ -92,6 +92,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -123,6 +124,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -162,6 +164,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -199,6 +202,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -250,6 +254,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -274,6 +279,7 @@ describe('create()', () => {
isPreconfigured: false,
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
});
expect(unsecuredSavedObjectsClient.create).toHaveBeenCalledTimes(1);
@ -283,6 +289,7 @@ describe('create()', () => {
Object {
"actionTypeId": "my-action-type",
"config": Object {},
"isMissingSecrets": false,
"name": "my name",
"secrets": Object {},
},
@ -347,6 +354,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {
a: true,
b: true,
@ -373,6 +381,7 @@ describe('create()', () => {
isPreconfigured: false,
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {
a: true,
b: true,
@ -390,6 +399,7 @@ describe('create()', () => {
"b": true,
"c": true,
},
"isMissingSecrets": false,
"name": "my name",
"secrets": Object {},
},
@ -449,6 +459,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -482,6 +493,7 @@ describe('create()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -518,6 +530,7 @@ describe('get()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -566,6 +579,7 @@ describe('get()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -628,6 +642,7 @@ describe('get()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -653,6 +668,7 @@ describe('get()', () => {
attributes: {
name: 'my name',
actionTypeId: 'my-action-type',
isMissingSecrets: false,
config: {},
},
references: [],
@ -821,6 +837,7 @@ describe('getAll()', () => {
type: 'type',
attributes: {
name: 'test',
isMissingSecrets: false,
config: {
foo: 'bar',
},
@ -881,6 +898,7 @@ describe('getAll()', () => {
type: 'type',
attributes: {
name: 'test',
isMissingSecrets: false,
config: {
foo: 'bar',
},
@ -932,6 +950,7 @@ describe('getAll()', () => {
config: {
foo: 'bar',
},
isMissingSecrets: false,
referencedByCount: 6,
},
{
@ -959,6 +978,7 @@ describe('getBulk()', () => {
config: {
foo: 'bar',
},
isMissingSecrets: false,
},
references: [],
},
@ -1030,6 +1050,7 @@ describe('getBulk()', () => {
config: {
foo: 'bar',
},
isMissingSecrets: false,
},
references: [],
},
@ -1088,6 +1109,7 @@ describe('getBulk()', () => {
config: {
foo: 'bar',
},
isMissingSecrets: false,
},
references: [],
},
@ -1143,6 +1165,7 @@ describe('getBulk()', () => {
foo: 'bar',
},
id: '1',
isMissingSecrets: false,
isPreconfigured: false,
name: 'test',
},
@ -1231,6 +1254,7 @@ describe('update()', () => {
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: false,
},
references: [],
});
@ -1239,6 +1263,7 @@ describe('update()', () => {
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: false,
name: 'my name',
config: {},
secrets: {},
@ -1319,6 +1344,7 @@ describe('update()', () => {
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: false,
},
references: [],
});
@ -1327,6 +1353,7 @@ describe('update()', () => {
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: false,
name: 'my name',
config: {},
secrets: {},
@ -1345,6 +1372,7 @@ describe('update()', () => {
id: 'my-action',
isPreconfigured: false,
actionTypeId: 'my-action-type',
isMissingSecrets: false,
name: 'my name',
config: {},
});
@ -1355,6 +1383,7 @@ describe('update()', () => {
Object {
"actionTypeId": "my-action-type",
"config": Object {},
"isMissingSecrets": false,
"name": "my name",
"secrets": Object {},
},
@ -1374,6 +1403,70 @@ describe('update()', () => {
`);
});
test('updates an action with isMissingSecrets "true" (set true as the import result), to isMissingSecrets', async () => {
actionTypeRegistry.register({
id: 'my-action-type',
name: 'My action type',
minimumLicenseRequired: 'basic',
executor,
});
unsecuredSavedObjectsClient.get.mockResolvedValueOnce({
id: '1',
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: true,
},
references: [],
});
unsecuredSavedObjectsClient.create.mockResolvedValueOnce({
id: 'my-action',
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: true,
name: 'my name',
config: {},
secrets: {},
},
references: [],
});
const result = await actionsClient.update({
id: 'my-action',
action: {
name: 'my name',
config: {},
secrets: {},
},
});
expect(result).toEqual({
id: 'my-action',
isPreconfigured: false,
actionTypeId: 'my-action-type',
isMissingSecrets: true,
name: 'my name',
config: {},
});
expect(unsecuredSavedObjectsClient.create).toHaveBeenCalledTimes(1);
expect(unsecuredSavedObjectsClient.create.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"action",
Object {
"actionTypeId": "my-action-type",
"config": Object {},
"isMissingSecrets": false,
"name": "my name",
"secrets": Object {},
},
Object {
"id": "my-action",
"overwrite": true,
"references": Array [],
},
]
`);
});
test('validates config', async () => {
actionTypeRegistry.register({
id: 'my-action-type',
@ -1428,6 +1521,7 @@ describe('update()', () => {
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: true,
name: 'my name',
config: {
a: true,
@ -1454,6 +1548,7 @@ describe('update()', () => {
id: 'my-action',
isPreconfigured: false,
actionTypeId: 'my-action-type',
isMissingSecrets: true,
name: 'my name',
config: {
a: true,
@ -1472,6 +1567,7 @@ describe('update()', () => {
"b": true,
"c": true,
},
"isMissingSecrets": false,
"name": "my name",
"secrets": Object {},
},
@ -1507,6 +1603,7 @@ describe('update()', () => {
type: 'action',
attributes: {
actionTypeId: 'my-action-type',
isMissingSecrets: false,
name: 'my name',
config: {},
secrets: {},

View file

@ -155,6 +155,7 @@ export class ActionsClient {
{
actionTypeId,
name,
isMissingSecrets: false,
config: validatedActionTypeConfig as SavedObjectAttributes,
secrets: validatedActionTypeSecrets as SavedObjectAttributes,
},
@ -164,6 +165,7 @@ export class ActionsClient {
return {
id: result.id,
actionTypeId: result.attributes.actionTypeId,
isMissingSecrets: result.attributes.isMissingSecrets,
name: result.attributes.name,
config: result.attributes.config,
isPreconfigured: false,
@ -228,6 +230,7 @@ export class ActionsClient {
...attributes,
actionTypeId,
name,
isMissingSecrets: false,
config: validatedActionTypeConfig as SavedObjectAttributes,
secrets: validatedActionTypeSecrets as SavedObjectAttributes,
},
@ -245,6 +248,7 @@ export class ActionsClient {
return {
id,
actionTypeId: result.attributes.actionTypeId as string,
isMissingSecrets: result.attributes.isMissingSecrets as boolean,
name: result.attributes.name as string,
config: result.attributes.config as Record<string, unknown>,
isPreconfigured: false,
@ -299,6 +303,7 @@ export class ActionsClient {
return {
id,
actionTypeId: result.attributes.actionTypeId,
isMissingSecrets: result.attributes.isMissingSecrets,
name: result.attributes.name,
config: result.attributes.config,
isPreconfigured: false,

View file

@ -39,12 +39,14 @@ describe('createActionRoute', () => {
actionTypeId: 'abc',
config: { foo: true },
isPreconfigured: false,
isMissingSecrets: false,
};
const createApiResult = {
...omit(createResult, ['actionTypeId', 'isPreconfigured']),
...omit(createResult, ['actionTypeId', 'isPreconfigured', 'isMissingSecrets']),
connector_type_id: createResult.actionTypeId,
is_preconfigured: createResult.isPreconfigured,
is_missing_secrets: createResult.isMissingSecrets,
};
const actionsClient = actionsClientMock.create();
@ -99,6 +101,7 @@ describe('createActionRoute', () => {
id: '1',
name: 'My name',
actionTypeId: 'abc',
isMissingSecrets: false,
config: { foo: true },
isPreconfigured: false,
});
@ -138,6 +141,7 @@ describe('createActionRoute', () => {
name: 'My name',
actionTypeId: 'abc',
config: { foo: true },
isMissingSecrets: false,
isPreconfigured: false,
});

View file

@ -29,11 +29,13 @@ const rewriteBodyReq: RewriteRequestCase<CreateOptions['action']> = ({
const rewriteBodyRes: RewriteResponseCase<ActionResult> = ({
actionTypeId,
isPreconfigured,
isMissingSecrets,
...res
}) => ({
...res,
connector_type_id: actionTypeId,
is_preconfigured: isPreconfigured,
is_missing_secrets: isMissingSecrets,
});
export const createActionRoute = (

View file

@ -38,6 +38,7 @@ describe('getActionRoute', () => {
name: 'action name',
config: {},
isPreconfigured: false,
isMissingSecrets: false,
};
const actionsClient = actionsClientMock.create();
@ -57,6 +58,7 @@ describe('getActionRoute', () => {
"config": Object {},
"connector_type_id": "2",
"id": "1",
"is_missing_secrets": false,
"is_preconfigured": false,
"name": "action name",
},
@ -73,6 +75,7 @@ describe('getActionRoute', () => {
name: 'action name',
config: {},
is_preconfigured: false,
is_missing_secrets: false,
},
});
});

View file

@ -19,11 +19,13 @@ const paramSchema = schema.object({
const rewriteBodyRes: RewriteResponseCase<ActionResult> = ({
actionTypeId,
isPreconfigured,
isMissingSecrets,
...res
}) => ({
...res,
connector_type_id: actionTypeId,
is_preconfigured: isPreconfigured,
is_missing_secrets: isMissingSecrets,
});
export const getActionRoute = (

View file

@ -12,12 +12,15 @@ import { ActionsRequestHandlerContext, FindActionResult } from '../types';
import { verifyAccessAndContext } from './verify_access_and_context';
const rewriteBodyRes: RewriteResponseCase<FindActionResult[]> = (results) => {
return results.map(({ actionTypeId, isPreconfigured, referencedByCount, ...res }) => ({
...res,
connector_type_id: actionTypeId,
is_preconfigured: isPreconfigured,
referenced_by_count: referencedByCount,
}));
return results.map(
({ actionTypeId, isPreconfigured, referencedByCount, isMissingSecrets, ...res }) => ({
...res,
connector_type_id: actionTypeId,
is_preconfigured: isPreconfigured,
referenced_by_count: referencedByCount,
is_missing_secrets: isMissingSecrets,
})
);
};
export const getAllActionRoute = (

View file

@ -25,11 +25,13 @@ const bodySchema = schema.object({
const rewriteBodyRes: RewriteResponseCase<ActionResult> = ({
actionTypeId,
isPreconfigured,
isMissingSecrets,
...res
}) => ({
...res,
connector_type_id: actionTypeId,
is_preconfigured: isPreconfigured,
is_missing_secrets: isMissingSecrets,
});
export const updateActionRoute = (

View file

@ -0,0 +1,53 @@
/*
* 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 { RawAction } from '../types';
import { getImportResultMessage } from './get_import_result_message';
describe('getImportResultMessage', () => {
it('Return message with total imported connectors and the proper secrets need to update ', async () => {
const savedObjectConnectors = [
{
type: 'action',
id: 'ed02cb70-a6ef-11eb-bd58-6b2eae02c6ef',
attributes: {
actionTypeId: '.server-log',
config: {},
isMissingSecrets: false,
name: 'test',
},
references: [],
migrationVersion: { action: '7.14.0' },
coreMigrationVersion: '8.0.0',
updated_at: '2021-04-27T04:10:33.043Z',
version: 'WzcxLDFd',
namespaces: ['default'],
},
{
type: 'action',
id: 'e8aa94e0-a6ef-11eb-bd58-6b2eae02c6ef',
attributes: {
actionTypeId: '.email',
config: [Object],
isMissingSecrets: true,
name: 'test',
},
references: [],
migrationVersion: { action: '7.14.0' },
coreMigrationVersion: '8.0.0',
updated_at: '2021-04-27T04:10:33.043Z',
version: 'WzcyLDFd',
namespaces: ['default'],
},
];
const message = getImportResultMessage(
(savedObjectConnectors as unknown) as Array<SavedObject<RawAction>>
);
expect(message).toBe('1 connector has secrets that require updates.');
});
});

View file

@ -0,0 +1,25 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { SavedObject } from 'kibana/server';
import { RawAction } from '../types';
export function getImportResultMessage(connectors: Array<SavedObject<RawAction>>) {
const connectorsWithSecrets = connectors.filter(
(connector) => connector.attributes.isMissingSecrets
);
return i18n.translate('xpack.actions.savedObjects.onImportText', {
defaultMessage:
'{connectorsWithSecretsLength} {connectorsWithSecretsLength, plural, one {connector has} other {connectors have}} secrets that require updates.',
values: {
connectorsWithSecretsLength: connectorsWithSecrets.length,
},
});
}
export const GO_TO_CONNECTORS_BUTTON_LABLE = 'Go to connectors';

View file

@ -5,10 +5,12 @@
* 2.0.
*/
import { SavedObjectsServiceSetup } from 'kibana/server';
import { SavedObject, SavedObjectsServiceSetup } from 'kibana/server';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import mappings from './mappings.json';
import { getMigrations } from './migrations';
import { RawAction } from '../types';
import { getImportResultMessage, GO_TO_CONNECTORS_BUTTON_LABLE } from './get_import_result_message';
export const ACTION_SAVED_OBJECT_TYPE = 'action';
export const ALERT_SAVED_OBJECT_TYPE = 'alert';
@ -24,6 +26,25 @@ export function setupSavedObjects(
namespaceType: 'single',
mappings: mappings.action,
migrations: getMigrations(encryptedSavedObjects),
management: {
defaultSearchField: 'name',
importableAndExportable: true,
getTitle(obj) {
return `Connector: [${obj.attributes.name}]`;
},
onImport(connectors) {
return {
warnings: [
{
type: 'action_required',
message: getImportResultMessage(connectors as Array<SavedObject<RawAction>>),
actionPath: '/app/management/insightsAndAlerting/triggersActions/connectors',
buttonLabel: GO_TO_CONNECTORS_BUTTON_LABLE,
},
],
};
},
},
});
// Encrypted attributes

View file

@ -12,6 +12,9 @@
"actionTypeId": {
"type": "keyword"
},
"isMissingSecrets": {
"type": "boolean"
},
"config": {
"enabled": false,
"type": "object"

View file

@ -43,7 +43,7 @@ describe('7.10.0', () => {
test('rename cases configuration object', () => {
const migration710 = getMigrations(encryptedSavedObjectsSetup)['7.10.0'];
const action = getMockData({});
const action = getCasesMockData({});
const migratedAction = migration710(action, context);
expect(migratedAction.attributes.config).toEqual({
incidentConfiguration: { mapping: [] },
@ -112,10 +112,32 @@ describe('7.11.0', () => {
});
});
describe('7.14.0', () => {
beforeEach(() => {
jest.resetAllMocks();
encryptedSavedObjectsSetup.createMigration.mockImplementation(
(shouldMigrateWhenPredicate, migration) => migration
);
});
test('add isMissingSecrets property for actions', () => {
const migration714 = getMigrations(encryptedSavedObjectsSetup)['7.14.0'];
const action = getMockData({ isMissingSecrets: undefined });
const migratedAction = migration714(action, context);
expect(migratedAction).toEqual({
...action,
attributes: {
...action.attributes,
isMissingSecrets: false,
},
});
});
});
function getMockDataForWebhook(
overwrites: Record<string, unknown> = {},
hasUserAndPassword: boolean
): SavedObjectUnsanitizedDoc<RawAction> {
): SavedObjectUnsanitizedDoc<Omit<RawAction, 'isMissingSecrets'>> {
const secrets = hasUserAndPassword
? { user: 'test', password: '123' }
: { user: '', password: '' };
@ -134,7 +156,7 @@ function getMockDataForWebhook(
function getMockDataForEmail(
overwrites: Record<string, unknown> = {}
): SavedObjectUnsanitizedDoc<RawAction> {
): SavedObjectUnsanitizedDoc<Omit<RawAction, 'isMissingSecrets'>> {
return {
attributes: {
name: 'abc',
@ -148,9 +170,9 @@ function getMockDataForEmail(
};
}
function getMockData(
function getCasesMockData(
overwrites: Record<string, unknown> = {}
): SavedObjectUnsanitizedDoc<RawAction> {
): SavedObjectUnsanitizedDoc<Omit<RawAction, 'isMissingSecrets'>> {
return {
attributes: {
name: 'abc',
@ -163,3 +185,19 @@ function getMockData(
type: 'action',
};
}
function getMockData(
overwrites: Record<string, unknown> = {}
): SavedObjectUnsanitizedDoc<Omit<RawAction, 'isMissingSecrets'>> {
return {
attributes: {
name: 'abc',
actionTypeId: '123',
config: {},
secrets: {},
...overwrites,
},
id: uuid.v4(),
type: 'action',
};
}

View file

@ -41,9 +41,15 @@ export function getMigrations(
pipeMigrations(removeCasesFieldMappings, addHasAuthConfigurationObject)
);
const migrationActionsFourteen = encryptedSavedObjects.createMigration<RawAction, RawAction>(
(doc): doc is SavedObjectUnsanitizedDoc<RawAction> => true,
pipeMigrations(addisMissingSecretsField)
);
return {
'7.10.0': executeMigrationWithErrorHandling(migrationActionsTen, '7.10.0'),
'7.11.0': executeMigrationWithErrorHandling(migrationActionsEleven, '7.11.0'),
'7.14.0': executeMigrationWithErrorHandling(migrationActionsFourteen, '7.14.0'),
};
}
@ -127,6 +133,18 @@ const addHasAuthConfigurationObject = (
};
};
const addisMissingSecretsField = (
doc: SavedObjectUnsanitizedDoc<RawAction>
): SavedObjectUnsanitizedDoc<RawAction> => {
return {
...doc,
attributes: {
...doc.attributes,
isMissingSecrets: false,
},
};
};
function pipeMigrations(...migrations: ActionMigration[]): ActionMigration {
return (doc: SavedObjectUnsanitizedDoc<RawAction>) =>
migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc);

View file

@ -63,6 +63,7 @@ export interface ActionResult<Config extends ActionTypeConfig = ActionTypeConfig
id: string;
actionTypeId: string;
name: string;
isMissingSecrets?: boolean;
config?: Config;
isPreconfigured: boolean;
}
@ -118,6 +119,7 @@ export interface ActionType<
export interface RawAction extends SavedObjectAttributes {
actionTypeId: string;
name: string;
isMissingSecrets: boolean;
config: SavedObjectAttributes;
secrets: SavedObjectAttributes;
}

View file

@ -41,6 +41,7 @@ export default function emailTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An email action',
connector_type_id: '.email',
is_missing_secrets: false,
config: {
service: '__json',
hasAuth: true,
@ -62,6 +63,7 @@ export default function emailTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An email action',
connector_type_id: '.email',
is_missing_secrets: false,
config: {
from: 'bob@example.com',
service: '__json',

View file

@ -43,6 +43,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An index action',
connector_type_id: '.index',
is_missing_secrets: false,
config: {
index: ES_TEST_INDEX_NAME,
refresh: false,
@ -59,6 +60,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
expect(fetchedAction).to.eql({
id: fetchedAction.id,
is_preconfigured: false,
is_missing_secrets: false,
name: 'An index action',
connector_type_id: '.index',
config: { index: ES_TEST_INDEX_NAME, refresh: false, executionTimeField: null },
@ -84,6 +86,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An index action with index config',
connector_type_id: '.index',
is_missing_secrets: false,
config: {
index: ES_TEST_INDEX_NAME,
refresh: true,
@ -102,6 +105,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An index action with index config',
connector_type_id: '.index',
is_missing_secrets: false,
config: {
index: ES_TEST_INDEX_NAME,
refresh: true,

View file

@ -78,6 +78,7 @@ export default function jiraTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A jira action',
connector_type_id: '.jira',
is_missing_secrets: false,
config: {
apiUrl: jiraSimulatorURL,
projectKey: mockJira.config.projectKey,
@ -93,6 +94,7 @@ export default function jiraTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A jira action',
connector_type_id: '.jira',
is_missing_secrets: false,
config: {
apiUrl: jiraSimulatorURL,
projectKey: mockJira.config.projectKey,

View file

@ -64,6 +64,7 @@ export default function pagerdutyTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A pagerduty action',
connector_type_id: '.pagerduty',
is_missing_secrets: false,
config: {
apiUrl: pagerdutySimulatorURL,
},
@ -80,6 +81,7 @@ export default function pagerdutyTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A pagerduty action',
connector_type_id: '.pagerduty',
is_missing_secrets: false,
config: {
apiUrl: pagerdutySimulatorURL,
},

View file

@ -81,6 +81,7 @@ export default function resilientTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An IBM Resilient action',
connector_type_id: '.resilient',
is_missing_secrets: false,
config: {
apiUrl: resilientSimulatorURL,
orgId: mockResilient.config.orgId,
@ -96,6 +97,7 @@ export default function resilientTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'An IBM Resilient action',
connector_type_id: '.resilient',
is_missing_secrets: false,
config: {
apiUrl: resilientSimulatorURL,
orgId: mockResilient.config.orgId,

View file

@ -30,6 +30,7 @@ export default function serverLogTest({ getService }: FtrProviderContext) {
expect(createdAction).to.eql({
id: createdAction.id,
is_preconfigured: false,
is_missing_secrets: false,
name: 'A server.log action',
connector_type_id: '.server-log',
config: {},
@ -46,6 +47,7 @@ export default function serverLogTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A server.log action',
connector_type_id: '.server-log',
is_missing_secrets: false,
config: {},
});
});

View file

@ -82,6 +82,7 @@ export default function servicenowTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A servicenow action',
connector_type_id: '.servicenow',
is_missing_secrets: false,
config: {
apiUrl: servicenowSimulatorURL,
},
@ -96,6 +97,7 @@ export default function servicenowTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A servicenow action',
connector_type_id: '.servicenow',
is_missing_secrets: false,
config: {
apiUrl: servicenowSimulatorURL,
},

View file

@ -59,6 +59,7 @@ export default function slackTest({ getService }: FtrProviderContext) {
expect(createdAction).to.eql({
id: createdAction.id,
is_preconfigured: false,
is_missing_secrets: false,
name: 'A slack action',
connector_type_id: '.slack',
config: {},
@ -73,6 +74,7 @@ export default function slackTest({ getService }: FtrProviderContext) {
expect(fetchedAction).to.eql({
id: fetchedAction.id,
is_preconfigured: false,
is_missing_secrets: false,
name: 'A slack action',
connector_type_id: '.slack',
config: {},

View file

@ -119,6 +119,7 @@ export default function webhookTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A generic Webhook action',
connector_type_id: '.webhook',
is_missing_secrets: false,
config: {
...defaultValues,
url: webhookSimulatorURL,
@ -136,6 +137,7 @@ export default function webhookTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A generic Webhook action',
connector_type_id: '.webhook',
is_missing_secrets: false,
config: {
...defaultValues,
url: webhookSimulatorURL,
@ -168,6 +170,7 @@ export default function webhookTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A generic Webhook action',
connector_type_id: '.webhook',
is_missing_secrets: false,
config: {
...defaultValues,
url: webhookSimulatorURL,
@ -204,6 +207,7 @@ export default function webhookTest({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'A generic Webhook action',
connector_type_id: '.webhook',
is_missing_secrets: false,
config: {
...defaultValues,
url: webhookSimulatorURL,

View file

@ -59,6 +59,7 @@ export default function createActionTests({ getService }: FtrProviderContext) {
expect(response.body).to.eql({
id: response.body.id,
is_preconfigured: false,
is_missing_secrets: false,
name: 'My action',
connector_type_id: 'test.index-record',
config: {

View file

@ -64,6 +64,7 @@ export default function getActionTests({ getService }: FtrProviderContext) {
id: createdAction.id,
is_preconfigured: false,
connector_type_id: 'test.index-record',
is_missing_secrets: false,
name: 'My action',
config: {
unencrypted: `This value shouldn't get encrypted`,

View file

@ -66,6 +66,7 @@ export default function getAllActionTests({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'My action',
connector_type_id: 'test.index-record',
is_missing_secrets: false,
config: {
unencrypted: `This value shouldn't get encrypted`,
},
@ -173,6 +174,7 @@ export default function getAllActionTests({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'My action',
connector_type_id: 'test.index-record',
is_missing_secrets: false,
config: {
unencrypted: `This value shouldn't get encrypted`,
},

View file

@ -74,6 +74,7 @@ export default function updateActionTests({ getService }: FtrProviderContext) {
id: createdAction.id,
is_preconfigured: false,
connector_type_id: 'test.index-record',
is_missing_secrets: false,
name: 'My action updated',
config: {
unencrypted: `This value shouldn't get encrypted`,

View file

@ -41,6 +41,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
isPreconfigured: false,
name: 'An index action',
actionTypeId: '.index',
isMissingSecrets: false,
config: {
index: ES_TEST_INDEX_NAME,
refresh: false,
@ -57,6 +58,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
expect(fetchedAction).to.eql({
id: fetchedAction.id,
isPreconfigured: false,
isMissingSecrets: false,
name: 'An index action',
actionTypeId: '.index',
config: { index: ES_TEST_INDEX_NAME, refresh: false, executionTimeField: null },
@ -82,6 +84,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
isPreconfigured: false,
name: 'An index action with index config',
actionTypeId: '.index',
isMissingSecrets: false,
config: {
index: ES_TEST_INDEX_NAME,
refresh: true,
@ -100,6 +103,7 @@ export default function indexTest({ getService }: FtrProviderContext) {
isPreconfigured: false,
name: 'An index action with index config',
actionTypeId: '.index',
isMissingSecrets: false,
config: {
index: ES_TEST_INDEX_NAME,
refresh: true,

View file

@ -41,6 +41,7 @@ export default function createActionTests({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'My action',
connector_type_id: 'test.index-record',
is_missing_secrets: false,
config: {
unencrypted: `This value shouldn't get encrypted`,
},
@ -79,6 +80,7 @@ export default function createActionTests({ getService }: FtrProviderContext) {
isPreconfigured: false,
name: 'My action',
actionTypeId: 'test.index-record',
isMissingSecrets: false,
config: {
unencrypted: `This value shouldn't get encrypted`,
},

View file

@ -40,6 +40,7 @@ export default function getActionTests({ getService }: FtrProviderContext) {
.expect(200, {
id: createdAction.id,
is_preconfigured: false,
is_missing_secrets: false,
connector_type_id: 'test.index-record',
name: 'My action',
config: {
@ -109,6 +110,7 @@ export default function getActionTests({ getService }: FtrProviderContext) {
id: createdAction.id,
isPreconfigured: false,
actionTypeId: 'test.index-record',
isMissingSecrets: false,
name: 'My action',
config: {
unencrypted: `This value shouldn't get encrypted`,

View file

@ -48,6 +48,7 @@ export default function getAllActionTests({ getService }: FtrProviderContext) {
is_preconfigured: false,
name: 'My action',
connector_type_id: 'test.index-record',
is_missing_secrets: false,
config: {
unencrypted: `This value shouldn't get encrypted`,
},
@ -171,6 +172,7 @@ export default function getAllActionTests({ getService }: FtrProviderContext) {
isPreconfigured: false,
name: 'My action',
actionTypeId: 'test.index-record',
isMissingSecrets: false,
config: {
unencrypted: `This value shouldn't get encrypted`,
},

View file

@ -55,5 +55,14 @@ export default function createGetTests({ getService }: FtrProviderContext) {
expect(responseNoAuth.body.config).key('hasAuth');
expect(responseNoAuth.body.config.hasAuth).to.eql(false);
});
it('7.14.0 migrates connectors to have `isMissingSecrets` property', async () => {
const responseWithisMissingSecrets = await supertest.get(
`${getUrlPrefix(``)}/api/actions/action/7434121e-045a-47d6-a0a6-0b6da752397a`
);
expect(responseWithisMissingSecrets.status).to.eql(200);
expect(responseWithisMissingSecrets.body.isMissingSecrets).to.eql(false);
});
});
}

View file

@ -62,6 +62,7 @@ export default function typeNotEnabledTests({ getService }: FtrProviderContext)
config: {},
id: 'uuid-actionId',
isPreconfigured: false,
isMissingSecrets: false,
name: 'an action created before test.not-enabled was disabled',
});
});
@ -89,6 +90,7 @@ export default function typeNotEnabledTests({ getService }: FtrProviderContext)
config: {},
id: 'uuid-actionId',
isPreconfigured: false,
isMissingSecrets: false,
name: 'an action created before test.not-enabled was disabled',
});
});

View file

@ -52,6 +52,7 @@ export default function updateActionTests({ getService }: FtrProviderContext) {
id: createdAction.id,
is_preconfigured: false,
connector_type_id: 'test.index-record',
is_missing_secrets: false,
name: 'My action updated',
config: {
unencrypted: `This value shouldn't get encrypted`,
@ -193,6 +194,7 @@ export default function updateActionTests({ getService }: FtrProviderContext) {
id: createdAction.id,
isPreconfigured: false,
actionTypeId: 'test.index-record',
isMissingSecrets: false,
name: 'My action updated',
config: {
unencrypted: `This value shouldn't get encrypted`,

View file

@ -92,6 +92,7 @@ export default ({ getService }: FtrProviderContext): void => {
projectKey: 'pkey',
},
isPreconfigured: false,
isMissingSecrets: false,
referencedByCount: 0,
},
{
@ -103,6 +104,7 @@ export default ({ getService }: FtrProviderContext): void => {
orgId: 'pkey',
},
isPreconfigured: false,
isMissingSecrets: false,
referencedByCount: 0,
},
{
@ -113,6 +115,7 @@ export default ({ getService }: FtrProviderContext): void => {
apiUrl: 'http://some.non.existent.com',
},
isPreconfigured: false,
isMissingSecrets: false,
referencedByCount: 0,
},
]);

View file

@ -87,6 +87,9 @@
"actionTypeId": {
"type": "keyword"
},
"isMissingSecrets": {
"type": "boolean"
},
"config": {
"enabled": false,
"type": "object"