[8.16] [ResponseOps][Actions] Allow to delete connectors with unsupported connector type using the API (#208033) (#208658)

# Backport

This will backport the following commits from `main` to `8.16`:
- [[ResponseOps][Actions] Allow to delete connectors with unsupported
connector type using the API
(#208033)](https://github.com/elastic/kibana/pull/208033)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Antonio","email":"antonio.coelho@elastic.co"},"sourceCommit":{"committedDate":"2025-01-29T00:37:12Z","message":"[ResponseOps][Actions]
Allow to delete connectors with unsupported connector type using the API
(#208033)\n\nCloses #207188\r\n\r\n## Summary\r\n\r\nThis is a freak
scenario that is hard to reproduce. That is why I did\r\nnot add a test
in\r\n`x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/delete.ts`.\r\nWe
cannot create a connector with an unregistered type so there is
no\r\nway to test deletion in the functional tests.\r\n\r\nI added a
unit test and there are steps below to test manually too.\r\n\r\n### How
to reproduce\r\n\r\n1. Create a connector, let's say `Pagerduty`.\r\n2.
Stop Kibana.\r\n3. Change the connector type id
in\r\n`stack_connectors/server/connector_types/pagerduty/index.ts`\r\n -
`'.pagerduty'` -> `'.pagerduty-foobar'`.\r\n- This will mean that when
you restart Kibana a new connector ID will be\r\nregistered and the
existing connector you created will be invalid/not\r\nsupported.\r\n4.
Restart Kibana.\r\n5. Try to delete the connector.\r\n\r\nIf this PR
works, you can delete the connector, and an error should be\r\nlogged in
the Kibana console.\r\n\r\nOn main the deletion would have
failed.","sha":"e5d38af58bbd6bd62c2869516c383383245a3d0d","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","Team:ResponseOps","v9.0.0","Feature:Actions/ConnectorsManagement","backport:prev-major"],"title":"[ResponseOps][Actions]
Allow to delete connectors with unsupported connector type using the
API","number":208033,"url":"https://github.com/elastic/kibana/pull/208033","mergeCommit":{"message":"[ResponseOps][Actions]
Allow to delete connectors with unsupported connector type using the API
(#208033)\n\nCloses #207188\r\n\r\n## Summary\r\n\r\nThis is a freak
scenario that is hard to reproduce. That is why I did\r\nnot add a test
in\r\n`x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/delete.ts`.\r\nWe
cannot create a connector with an unregistered type so there is
no\r\nway to test deletion in the functional tests.\r\n\r\nI added a
unit test and there are steps below to test manually too.\r\n\r\n### How
to reproduce\r\n\r\n1. Create a connector, let's say `Pagerduty`.\r\n2.
Stop Kibana.\r\n3. Change the connector type id
in\r\n`stack_connectors/server/connector_types/pagerduty/index.ts`\r\n -
`'.pagerduty'` -> `'.pagerduty-foobar'`.\r\n- This will mean that when
you restart Kibana a new connector ID will be\r\nregistered and the
existing connector you created will be invalid/not\r\nsupported.\r\n4.
Restart Kibana.\r\n5. Try to delete the connector.\r\n\r\nIf this PR
works, you can delete the connector, and an error should be\r\nlogged in
the Kibana console.\r\n\r\nOn main the deletion would have
failed.","sha":"e5d38af58bbd6bd62c2869516c383383245a3d0d"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/208033","number":208033,"mergeCommit":{"message":"[ResponseOps][Actions]
Allow to delete connectors with unsupported connector type using the API
(#208033)\n\nCloses #207188\r\n\r\n## Summary\r\n\r\nThis is a freak
scenario that is hard to reproduce. That is why I did\r\nnot add a test
in\r\n`x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/delete.ts`.\r\nWe
cannot create a connector with an unregistered type so there is
no\r\nway to test deletion in the functional tests.\r\n\r\nI added a
unit test and there are steps below to test manually too.\r\n\r\n### How
to reproduce\r\n\r\n1. Create a connector, let's say `Pagerduty`.\r\n2.
Stop Kibana.\r\n3. Change the connector type id
in\r\n`stack_connectors/server/connector_types/pagerduty/index.ts`\r\n -
`'.pagerduty'` -> `'.pagerduty-foobar'`.\r\n- This will mean that when
you restart Kibana a new connector ID will be\r\nregistered and the
existing connector you created will be invalid/not\r\nsupported.\r\n4.
Restart Kibana.\r\n5. Try to delete the connector.\r\n\r\nIf this PR
works, you can delete the connector, and an error should be\r\nlogged in
the Kibana console.\r\n\r\nOn main the deletion would have
failed.","sha":"e5d38af58bbd6bd62c2869516c383383245a3d0d"}}]}]
BACKPORT-->

Co-authored-by: Antonio <antonio.coelho@elastic.co>
This commit is contained in:
Kibana Machine 2025-01-29 13:23:25 +11:00 committed by GitHub
parent 2599c82f58
commit 3512420dbf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 98 additions and 3 deletions

View file

@ -2170,6 +2170,39 @@ describe('delete()', () => {
`"System action system-connector-.cases is not allowed to delete."`
);
});
test('deleting unregistered action types works as expected', async () => {
const expectedResult = Symbol();
unsecuredSavedObjectsClient.delete.mockResolvedValueOnce(expectedResult);
unsecuredSavedObjectsClient.get = jest.fn().mockResolvedValueOnce({
id: '2',
type: 'action',
attributes: {
actionTypeId: 'unregistered-action-type-id',
isMissingSecrets: false,
config: {},
secrets: {},
},
references: [],
});
const result = await actionsClient.delete({ id: '2' });
expect(result).toEqual(expectedResult);
// the event is logged but no error is thrown as expected
expect(logger.error).toHaveBeenCalledWith(
`Failed fetching action type from registry: Action type \"unregistered-action-type-id\" is not registered. - deletion will proceed.`
);
// deletion is called with the right params
expect(unsecuredSavedObjectsClient.delete).toHaveBeenCalledTimes(1);
expect(unsecuredSavedObjectsClient.delete.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"action",
"2",
]
`);
});
});
describe('update()', () => {

View file

@ -43,6 +43,7 @@ import {
ActionTypeExecutorResult,
ConnectorTokenClientContract,
HookServices,
ActionType,
} from '../types';
import { PreconfiguredActionDisabledModificationError } from '../lib/errors/preconfigured_action_disabled_modification';
import {
@ -460,14 +461,22 @@ export class ActionsClient {
attributes: { actionTypeId, config },
} = rawAction;
const actionType = this.context.actionTypeRegistry.get(actionTypeId);
let actionType: ActionType | undefined;
try {
actionType = this.context.actionTypeRegistry.get(actionTypeId);
} catch (e) {
this.context.logger.error(
`Failed fetching action type from registry: ${e.message} - deletion will proceed.`
);
}
const result = await this.context.unsecuredSavedObjectsClient.delete('action', id);
const hookServices: HookServices = {
scopedClusterClient: this.context.scopedClusterClient,
};
if (actionType.postDeleteHook) {
if (actionType && actionType.postDeleteHook) {
try {
await actionType.postDeleteHook({
connectorId: id,

View file

@ -9,7 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
import expect from '@kbn/expect';
import { ESTestIndexTool, ES_TEST_INDEX_NAME } from '@kbn/alerting-api-integration-helpers';
import { UserAtSpaceScenarios } from '../../../scenarios';
import { UserAtSpaceScenarios, SuperuserAtSpace1 } from '../../../scenarios';
import { getUrlPrefix, ObjectRemover } from '../../../../common/lib';
import { FtrProviderContext } from '../../../../common/ftr_provider_context';
@ -19,6 +19,8 @@ export default function deleteActionTests({ getService }: FtrProviderContext) {
const supertestWithoutAuth = getService('supertestWithoutAuth');
const es = getService('es');
const retry = getService('retry');
const kibanaServer = getService('kibanaServer');
const esTestIndexTool = new ESTestIndexTool(es, retry);
describe('delete', () => {
@ -28,6 +30,7 @@ export default function deleteActionTests({ getService }: FtrProviderContext) {
await esTestIndexTool.destroy();
await esTestIndexTool.setup();
});
after(async () => {
await esTestIndexTool.destroy();
await objectRemover.removeAll();
@ -297,5 +300,35 @@ export default function deleteActionTests({ getService }: FtrProviderContext) {
});
});
}
it('should delete a connector with an unsupported type', async () => {
await kibanaServer.importExport.load(
'x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/fixtures/unsupported_connector_type.json'
);
const { space, user } = SuperuserAtSpace1;
const { body: createdConnector } = await supertest
.post(`${getUrlPrefix(space.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'My Connector',
connector_type_id: 'test.index-record',
config: {
unencrypted: `This value shouldn't get encrypted`,
},
secrets: {
encrypted: 'This value should be encrypted',
},
})
.expect(200);
const response = await supertestWithoutAuth
.delete(`${getUrlPrefix(space.id)}/api/actions/connector/${createdConnector.id}`)
.auth(user.username, user.password)
.set('kbn-xsrf', 'foo');
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
});
});
}

View file

@ -0,0 +1,20 @@
{
"attributes": {
"actionTypeId": ".invalid-type",
"config": {
"apiUrl": "https://localhost:5601/"
},
"isMissingSecrets": true,
"name": "Invalid connector",
"secrets": {}
},
"coreMigrationVersion": "8.8.0",
"created_at": "2025-01-28T08:46:46.614Z",
"id": "e6dca811-c3c1-4eca-8eb0-54c792c0b662",
"managed": false,
"references": [],
"type": "action",
"typeMigrationVersion": "10.1.0",
"updated_at": "2025-01-28T08:46:46.614Z",
"version": "WzUsMl0="
}