diff --git a/src/plugins/data_source/common/data_sources/types.ts b/src/plugins/data_source/common/data_sources/types.ts index 0005efd490b2..afcf3d662fed 100644 --- a/src/plugins/data_source/common/data_sources/types.ts +++ b/src/plugins/data_source/common/data_sources/types.ts @@ -9,10 +9,9 @@ export interface DataSourceAttributes extends SavedObjectAttributes { title: string; description?: string; endpoint: string; - noAuth: boolean; - credentials?: { - type: CredentialsType; - credentialsContent: UsernamePasswordTypedContent; + auth: { + type: AuthType; + credentials: UsernamePasswordTypedContent | undefined; }; } @@ -21,6 +20,7 @@ export interface UsernamePasswordTypedContent extends SavedObjectAttributes { password: string; } -export enum CredentialsType { +export enum AuthType { + NoAuth = 'no_auth', UsernamePasswordType = 'username_password', } 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 63cc18d7a3cb..a12a46f40cd4 100644 --- a/src/plugins/data_source/server/client/configure_client.test.ts +++ b/src/plugins/data_source/server/client/configure_client.test.ts @@ -6,7 +6,7 @@ import { SavedObjectsClientContract } from '../../../../core/server'; import { loggingSystemMock, savedObjectsClientMock } from '../../../../core/server/mocks'; import { DATA_SOURCE_SAVED_OBJECT_TYPE } from '../../common'; -import { DataSourceAttributes, CredentialsType } from '../../common/data_sources/types'; +import { DataSourceAttributes, AuthType } from '../../common/data_sources/types'; import { DataSourcePluginConfigType } from '../../config'; import { ClientMock, parseClientOptionsMock } from './configure_client.test.mocks'; import { OpenSearchClientPoolSetup } from './client_pool'; @@ -49,10 +49,9 @@ describe('configureClient', () => { dataSourceAttr = { title: 'title', endpoint: 'http://localhost', - noAuth: false, - credentials: { - type: CredentialsType.UsernamePasswordType, - credentialsContent: { + auth: { + type: AuthType.UsernamePasswordType, + credentials: { username: 'username', password: 'password', }, @@ -80,11 +79,16 @@ describe('configureClient', () => { ClientMock.mockReset(); }); - test('configure client with noAuth == true, will call new Client() to create client', async () => { + test('configure client with auth.type == no_auth, will call new Client() to create client', async () => { savedObjectsMock.get.mockReset().mockResolvedValueOnce({ id: DATA_SOURCE_ID, type: DATA_SOURCE_SAVED_OBJECT_TYPE, - attributes: { ...dataSourceAttr, noAuth: true }, + attributes: { + ...dataSourceAttr, + auth: { + type: AuthType.NoAuth, + }, + }, references: [], }); diff --git a/src/plugins/data_source/server/client/configure_client.ts b/src/plugins/data_source/server/client/configure_client.ts index e24cfe7b9930..5ba18261ba74 100644 --- a/src/plugins/data_source/server/client/configure_client.ts +++ b/src/plugins/data_source/server/client/configure_client.ts @@ -12,7 +12,11 @@ import { } from '../../../../../src/core/server'; import { DATA_SOURCE_SAVED_OBJECT_TYPE } from '../../common'; -import { DataSourceAttributes, UsernamePasswordTypedContent } from '../../common/data_sources'; +import { + AuthType, + DataSourceAttributes, + UsernamePasswordTypedContent, +} from '../../common/data_sources'; import { DataSourcePluginConfigType } from '../../config'; import { CryptographyClient } from '../cryptography'; import { parseClientOptions } from './client_config'; @@ -53,7 +57,7 @@ export const getCredential = async ( cryptographyClient: CryptographyClient ): Promise => { try { - const { username, password } = dataSource.attributes.credentials!.credentialsContent; + const { username, password } = dataSource.attributes.auth.credentials!; const decodedPassword = await cryptographyClient.decodeAndDecrypt(password); const credential = { username, @@ -72,7 +76,7 @@ export const getCredential = async ( * * @param rootClient root client for the connection with given data source endpoint. * @param dataSource data source saved object - * @param savedObjects scoped saved object client + * @param cryptographyClient cryptography client for password encryption / decrpytion * @returns child client. */ const getQueryClient = async ( @@ -80,7 +84,7 @@ const getQueryClient = async ( dataSource: SavedObject, cryptographyClient: CryptographyClient ): Promise => { - if (dataSource.attributes.noAuth) { + if (AuthType.NoAuth === dataSource.attributes.auth.type) { return rootClient.child(); } else { const credential = await getCredential(dataSource, cryptographyClient); diff --git a/src/plugins/data_source/server/saved_objects/data_source_saved_objects_client_wrapper.ts b/src/plugins/data_source/server/saved_objects/data_source_saved_objects_client_wrapper.ts index e90a408b4584..f2f2bbbf62f7 100644 --- a/src/plugins/data_source/server/saved_objects/data_source_saved_objects_client_wrapper.ts +++ b/src/plugins/data_source/server/saved_objects/data_source_saved_objects_client_wrapper.ts @@ -20,7 +20,7 @@ import { SavedObjectsErrorHelpers } from '../../../../core/server'; import { CryptographyClient } from '../cryptography'; import { DATA_SOURCE_SAVED_OBJECT_TYPE } from '../../common'; -import { CredentialsType } from '../../common/data_sources'; +import { AuthType } from '../../common/data_sources'; /** * Describes the Credential Saved Objects Client Wrapper class, @@ -137,56 +137,52 @@ export class DataSourceSavedObjectsClientWrapper { } } - private dropCredentials(attributes: Omit) { - return attributes; - } - private async validateAndEncryptAttributes(attributes: T) { this.validateAttributes(attributes); - const { noAuth } = attributes; - - // Drop credentials when no Auth - if (!noAuth) { - return this.dropCredentials(attributes); - } - - const { type, credentialsContent } = attributes.credentials; + const { type, credentials } = attributes.auth; switch (type) { - case CredentialsType.UsernamePasswordType: - const { username, password } = credentialsContent; + case AuthType.NoAuth: + return { + ...attributes, + // Drop the credentials attribute for no_auth + credentials: undefined, + }; + case AuthType.UsernamePasswordType: + const { username, password } = credentials; return { ...attributes, credentials: { - type, - credentialsContent: { - username, - password: await this.cryptographyClient.encryptAndEncode(password), - }, + username, + password: await this.cryptographyClient.encryptAndEncode(password), }, }; default: - throw SavedObjectsErrorHelpers.createBadRequestError( - `Invalid credential materials type: '${type}'` - ); + throw SavedObjectsErrorHelpers.createBadRequestError(`Invalid auth type: '${type}'`); } } private async validateAndUpdatePartialAttributes(attributes: T) { - const { noAuth, credentials } = attributes; + const { auth } = attributes; - // Drop credentials when no Auth - if (!noAuth) { - return this.dropCredentials(attributes); + if (auth === undefined) { + return attributes; } - const { type, credentialsContent } = credentials; + const { type, credentials } = auth; switch (type) { - case CredentialsType.UsernamePasswordType: - if ('password' in credentialsContent) { - const { username, password } = credentialsContent; + case AuthType.NoAuth: + return { + ...attributes, + // Drop the credentials attribute for no_auth + credentials: undefined, + }; + case AuthType.UsernamePasswordType: + const { username, password } = credentials; + + if (password) { return { ...attributes, credentials: { @@ -206,61 +202,64 @@ export class DataSourceSavedObjectsClientWrapper { } private validateAttributes(attributes: T) { - const { title, endpoint, noAuth, credentials } = attributes; + const { title, endpoint, auth } = attributes; if (!title) { - throw SavedObjectsErrorHelpers.createBadRequestError('attribute "title" required'); + throw SavedObjectsErrorHelpers.createBadRequestError( + 'attribute "title" required for "data source" saved object' + ); } if (!this.isValidUrl(endpoint)) { - throw SavedObjectsErrorHelpers.createBadRequestError('attribute "endpoint" is not valid'); + throw SavedObjectsErrorHelpers.createBadRequestError( + 'attribute "endpoint" is not valid for "data source" saved object' + ); } - if (noAuth) { - this.validateCredentials(credentials); + if (auth === undefined) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'attribute "auth" required for "data source" saved object' + ); } - } - private validateCredentials(credentials: T) { - if (credentials === undefined) { - throw SavedObjectsErrorHelpers.createBadRequestError('attribute "credentials" required'); - } + this.validateAuth(auth); + } - const { type, credentialsContent } = credentials; + private validateAuth(auth: T) { + const { type, credentials } = auth; if (!type) { throw SavedObjectsErrorHelpers.createBadRequestError( - 'attribute "type" required for "credentials"' - ); - } - - if (credentialsContent === undefined) { - throw SavedObjectsErrorHelpers.createBadRequestError( - 'attribute "credentialsContent" required for "credentials"' + 'attribute "auth.type" required for "data source" saved object' ); } switch (type) { - case CredentialsType.UsernamePasswordType: - const { username, password } = credentialsContent; + case AuthType.NoAuth: + break; + case AuthType.UsernamePasswordType: + if (credentials === undefined) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'attribute "auth.credentials" required for "data source" saved object' + ); + } - this.validateUsername(username); - this.validatePassword(password); - default: - throw SavedObjectsErrorHelpers.createBadRequestError(`Invalid credentials type: '${type}'`); - } - } + const { username, password } = credentials; - private validateUsername(username: T) { - if (!username) { - throw SavedObjectsErrorHelpers.createBadRequestError('attribute "username" required'); - } - return; - } + if (!username) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'attribute "auth.credentials.username" required' + ); + } - private validatePassword(password: T) { - if (!password) { - throw SavedObjectsErrorHelpers.createBadRequestError('attribute "password" required'); + if (!password) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'attribute "auth.credentials.password" required' + ); + } + + break; + default: + throw SavedObjectsErrorHelpers.createBadRequestError(`Invalid auth type: '${type}'`); } - return; } }