diff --git a/CHANGELOG.md b/CHANGELOG.md index 9933dd763a61..47a5da73a904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Multiple Datasource] Add interfaces to register add-on authentication method from plug-in module ([#5851](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5851)) - [Multiple Datasource] Able to Hide "Local Cluster" option from datasource DropDown ([#5827](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5827)) - [Multiple Datasource] Add api registry and allow it to be added into client config in data source plugin ([#5895](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5895)) +- [Multiple Datasource] Refactor client and legacy client to use authentication registry ([#5881](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5881)) ### 🐛 Bug Fixes diff --git a/src/plugins/data_source/server/auth_registry/authentication_methods_registry.mock.ts b/src/plugins/data_source/server/auth_registry/authentication_methods_registry.mock.ts new file mode 100644 index 000000000000..41e63798556e --- /dev/null +++ b/src/plugins/data_source/server/auth_registry/authentication_methods_registry.mock.ts @@ -0,0 +1,14 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { IAuthenticationMethodRegistery } from './authentication_methods_registry'; + +const create = () => + (({ + getAllAuthenticationMethods: jest.fn(), + getAuthenticationMethod: jest.fn(), + } as unknown) as jest.Mocked); + +export const authenticationMethodRegisteryMock = { create }; diff --git a/src/plugins/data_source/server/auth_registry/index.ts b/src/plugins/data_source/server/auth_registry/index.ts index 9352afd8b661..919585a26b96 100644 --- a/src/plugins/data_source/server/auth_registry/index.ts +++ b/src/plugins/data_source/server/auth_registry/index.ts @@ -7,3 +7,5 @@ export { IAuthenticationMethodRegistery, AuthenticationMethodRegistery, } from './authentication_methods_registry'; + +export { authenticationMethodRegisteryMock } from './authentication_methods_registry.mock'; diff --git a/src/plugins/data_source/server/client/configure_client.test.mocks.ts b/src/plugins/data_source/server/client/configure_client.test.mocks.ts index 38a585ff2020..787954a5f97b 100644 --- a/src/plugins/data_source/server/client/configure_client.test.mocks.ts +++ b/src/plugins/data_source/server/client/configure_client.test.mocks.ts @@ -16,3 +16,8 @@ export const parseClientOptionsMock = jest.fn(); jest.doMock('./client_config', () => ({ parseClientOptions: parseClientOptionsMock, })); + +export const authRegistryCredentialProviderMock = jest.fn(); +jest.doMock('../util/credential_provider', () => ({ + authRegistryCredentialProvider: authRegistryCredentialProviderMock, +})); diff --git a/src/plugins/data_source/server/client/configure_client.test.ts b/src/plugins/data_source/server/client/configure_client.test.ts index dc0fc2691a83..e7344b2fa521 100644 --- a/src/plugins/data_source/server/client/configure_client.test.ts +++ b/src/plugins/data_source/server/client/configure_client.test.ts @@ -13,7 +13,11 @@ import { SigV4Content, } from '../../common/data_sources/types'; import { DataSourcePluginConfigType } from '../../config'; -import { ClientMock, parseClientOptionsMock } from './configure_client.test.mocks'; +import { + ClientMock, + parseClientOptionsMock, + authRegistryCredentialProviderMock, +} from './configure_client.test.mocks'; import { OpenSearchClientPoolSetup } from './client_pool'; import { configureClient } from './configure_client'; import { ClientOptions } from '@opensearch-project/opensearch'; @@ -21,8 +25,12 @@ import { ClientOptions } from '@opensearch-project/opensearch'; import { opensearchClientMock } from '../../../../core/server/opensearch/client/mocks'; import { cryptographyServiceSetupMock } from '../cryptography_service.mocks'; import { CryptographyServiceSetup } from '../cryptography_service'; -import { DataSourceClientParams } from '../types'; +import { DataSourceClientParams, AuthenticationMethod } from '../types'; import { CustomApiSchemaRegistry } from '../schema_registry'; +import { + IAuthenticationMethodRegistery, + authenticationMethodRegisteryMock, +} from '../auth_registry'; const DATA_SOURCE_ID = 'a54b76ec86771ee865a0f74a305dfff8'; @@ -40,6 +48,7 @@ describe('configureClient', () => { let usernamePasswordAuthContent: UsernamePasswordTypedContent; let sigV4AuthContent: SigV4Content; let customApiSchemaRegistry: CustomApiSchemaRegistry; + let authenticationMethodRegistery: jest.Mocked; beforeEach(() => { dsClient = opensearchClientMock.createInternalClient(); @@ -47,6 +56,7 @@ describe('configureClient', () => { savedObjectsMock = savedObjectsClientMock.create(); cryptographyMock = cryptographyServiceSetupMock.create(); customApiSchemaRegistry = new CustomApiSchemaRegistry(); + authenticationMethodRegistery = authenticationMethodRegisteryMock.create(); config = { enabled: true, @@ -242,4 +252,46 @@ describe('configureClient', () => { expect(savedObjectsMock.get).toHaveBeenCalledTimes(1); expect(decodeAndDecryptSpy).toHaveBeenCalledTimes(1); }); + + test('configureClient should retunrn client from authentication registery if method present in registry', async () => { + const name = 'typeA'; + const customAuthContent = { + region: 'us-east-1', + roleARN: 'test-role', + }; + savedObjectsMock.get.mockReset().mockResolvedValueOnce({ + id: DATA_SOURCE_ID, + type: DATA_SOURCE_SAVED_OBJECT_TYPE, + attributes: { + ...dataSourceAttr, + auth: { + type: AuthType.SigV4, + credentials: customAuthContent, + }, + }, + references: [], + }); + const authMethod: AuthenticationMethod = { + name, + authType: AuthType.SigV4, + credentialProvider: jest.fn(), + }; + authenticationMethodRegistery.getAuthenticationMethod.mockImplementation(() => authMethod); + + authRegistryCredentialProviderMock.mockReturnValue({ + credential: sigV4AuthContent, + type: AuthType.SigV4, + }); + + await configureClient( + { ...dataSourceClientParams, authRegistry: authenticationMethodRegistery }, + clientPoolSetup, + config, + logger + ); + expect(authRegistryCredentialProviderMock).toHaveBeenCalled(); + expect(authenticationMethodRegistery.getAuthenticationMethod).toHaveBeenCalledTimes(1); + expect(ClientMock).toHaveBeenCalledTimes(1); + expect(savedObjectsMock.get).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/plugins/data_source/server/legacy/configure_legacy_client.test.mocks.ts b/src/plugins/data_source/server/legacy/configure_legacy_client.test.mocks.ts index e6c1b3363896..2f91e757fd28 100644 --- a/src/plugins/data_source/server/legacy/configure_legacy_client.test.mocks.ts +++ b/src/plugins/data_source/server/legacy/configure_legacy_client.test.mocks.ts @@ -16,3 +16,8 @@ export const parseClientOptionsMock = jest.fn(); jest.doMock('./client_config', () => ({ parseClientOptions: parseClientOptionsMock, })); + +export const authRegistryCredentialProviderMock = jest.fn(); +jest.doMock('../util/credential_provider', () => ({ + authRegistryCredentialProvider: authRegistryCredentialProviderMock, +})); diff --git a/src/plugins/data_source/server/legacy/configure_legacy_client.test.ts b/src/plugins/data_source/server/legacy/configure_legacy_client.test.ts index f5cae1307f5a..c55715ea3fe7 100644 --- a/src/plugins/data_source/server/legacy/configure_legacy_client.test.ts +++ b/src/plugins/data_source/server/legacy/configure_legacy_client.test.ts @@ -10,12 +10,20 @@ import { AuthType, DataSourceAttributes, SigV4Content } from '../../common/data_ import { DataSourcePluginConfigType } from '../../config'; import { cryptographyServiceSetupMock } from '../cryptography_service.mocks'; import { CryptographyServiceSetup } from '../cryptography_service'; -import { DataSourceClientParams, LegacyClientCallAPIParams } from '../types'; +import { DataSourceClientParams, LegacyClientCallAPIParams, AuthenticationMethod } from '../types'; import { OpenSearchClientPoolSetup } from '../client'; import { ConfigOptions } from 'elasticsearch'; -import { ClientMock, parseClientOptionsMock } from './configure_legacy_client.test.mocks'; +import { + ClientMock, + parseClientOptionsMock, + authRegistryCredentialProviderMock, +} from './configure_legacy_client.test.mocks'; import { configureLegacyClient } from './configure_legacy_client'; import { CustomApiSchemaRegistry } from '../schema_registry'; +import { + IAuthenticationMethodRegistery, + authenticationMethodRegisteryMock, +} from '../auth_registry'; const DATA_SOURCE_ID = 'a54b76ec86771ee865a0f74a305dfff8'; @@ -29,6 +37,7 @@ describe('configureLegacyClient', () => { let configOptions: ConfigOptions; let dataSourceAttr: DataSourceAttributes; let sigV4AuthContent: SigV4Content; + let authenticationMethodRegistery: jest.Mocked; let mockOpenSearchClientInstance: { close: jest.Mock; @@ -48,6 +57,7 @@ describe('configureLegacyClient', () => { logger = loggingSystemMock.createLogger(); savedObjectsMock = savedObjectsClientMock.create(); cryptographyMock = cryptographyServiceSetupMock.create(); + authenticationMethodRegistery = authenticationMethodRegisteryMock.create(); config = { enabled: true, clientPool: { @@ -254,4 +264,47 @@ describe('configureLegacyClient', () => { expect(mockOpenSearchClientInstance.ping).toHaveBeenCalledTimes(1); expect(mockOpenSearchClientInstance.ping).toHaveBeenLastCalledWith(mockParams); }); + + test('configureLegacyClient should retunrn client from authentication registery if method present in registry', async () => { + const name = 'typeA'; + const customAuthContent = { + region: 'us-east-1', + roleARN: 'test-role', + }; + savedObjectsMock.get.mockReset().mockResolvedValueOnce({ + id: DATA_SOURCE_ID, + type: DATA_SOURCE_SAVED_OBJECT_TYPE, + attributes: { + ...dataSourceAttr, + auth: { + type: AuthType.SigV4, + credentials: customAuthContent, + }, + }, + references: [], + }); + const authMethod: AuthenticationMethod = { + name, + authType: AuthType.SigV4, + credentialProvider: jest.fn(), + }; + authenticationMethodRegistery.getAuthenticationMethod.mockImplementation(() => authMethod); + + authRegistryCredentialProviderMock.mockReturnValue({ + credential: sigV4AuthContent, + type: AuthType.SigV4, + }); + + await configureLegacyClient( + { ...dataSourceClientParams, authRegistry: authenticationMethodRegistery }, + callApiParams, + clientPoolSetup, + config, + logger + ); + expect(authRegistryCredentialProviderMock).toHaveBeenCalled(); + expect(authenticationMethodRegistery.getAuthenticationMethod).toHaveBeenCalledTimes(1); + expect(ClientMock).toHaveBeenCalledTimes(1); + expect(savedObjectsMock.get).toHaveBeenCalledTimes(1); + }); });