Skip to content

Commit

Permalink
[8.12][Fleet] support toggle between secret and plain text storage (e…
Browse files Browse the repository at this point in the history
  • Loading branch information
juliaElastic authored Jan 15, 2024
1 parent 24733e5 commit 3c7c2f1
Show file tree
Hide file tree
Showing 11 changed files with 620 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
*/

import React from 'react';
import { fireEvent, waitFor } from '@testing-library/react';

import type { Output } from '../../../../types';
import { createFleetTestRendererMock } from '../../../../../../mock';
import { useFleetStatus } from '../../../../../../hooks/use_fleet_status';
import { ExperimentalFeaturesService } from '../../../../../../services';
import { useStartServices } from '../../../../hooks';
import { useStartServices, sendPutOutput } from '../../../../hooks';

import { EditOutputFlyout } from '.';

Expand All @@ -31,9 +32,15 @@ jest.mock('../../../../hooks', () => {
...jest.requireActual('../../../../hooks'),
useBreadcrumbs: jest.fn(),
useStartServices: jest.fn(),
sendPutOutput: jest.fn(),
};
});

jest.mock('./confirm_update', () => ({
confirmUpdate: () => jest.fn().mockResolvedValue(true),
}));

const mockSendPutOutput = sendPutOutput as jest.MockedFunction<typeof sendPutOutput>;
const mockUseStartServices = useStartServices as jest.Mock;

const mockedUsedFleetStatus = useFleetStatus as jest.MockedFunction<typeof useFleetStatus>;
Expand Down Expand Up @@ -80,7 +87,11 @@ const remoteEsOutputLabels = ['Hosts', 'Service Token'];
describe('EditOutputFlyout', () => {
const mockStartServices = (isServerlessEnabled?: boolean) => {
mockUseStartServices.mockReturnValue({
notifications: { toasts: {} },
notifications: {
toasts: {
addError: jest.fn(),
},
},
docLinks: {
links: { fleet: {}, logstash: {}, kibana: {} },
},
Expand All @@ -92,6 +103,9 @@ describe('EditOutputFlyout', () => {

beforeEach(() => {
mockStartServices(false);
jest.clearAllMocks();
// mockSendPutOutput.mockClear();
// mockedUsedFleetStatus.mockClear();
});

it('should render the flyout if there is not output provided', async () => {
Expand Down Expand Up @@ -174,6 +188,102 @@ describe('EditOutputFlyout', () => {
});
});

it('should populate secret input with plain text value when editing kafka output', async () => {
jest
.spyOn(ExperimentalFeaturesService, 'get')
.mockReturnValue({ outputSecretsStorage: true, kafkaOutput: true });
const { utils } = renderFlyout({
type: 'kafka',
name: 'kafka output',
id: 'outputK',
is_default: false,
is_default_monitoring: false,
hosts: ['kafka:443'],
topics: [{ topic: 'topic' }],
auth_type: 'ssl',
version: '1.0.0',
ssl: { certificate: 'cert', key: 'key', verification_mode: 'full' },
compression: 'none',
});

expect((utils.getByTestId('kafkaSslKeySecretInput') as any).value).toEqual('key');

fireEvent.click(utils.getByText('Save and apply settings'));

await waitFor(() => {
expect(mockSendPutOutput).toHaveBeenCalledWith(
'outputK',
expect.objectContaining({
secrets: { ssl: { key: 'key' } },
ssl: { certificate: 'cert', key: '', verification_mode: 'full' },
})
);
});
});

it('should populate secret password input with plain text value when editing kafka output', async () => {
jest
.spyOn(ExperimentalFeaturesService, 'get')
.mockReturnValue({ outputSecretsStorage: true, kafkaOutput: true });
const { utils } = renderFlyout({
type: 'kafka',
name: 'kafka output',
id: 'outputK',
is_default: false,
is_default_monitoring: false,
hosts: ['kafka:443'],
topics: [{ topic: 'topic' }],
auth_type: 'user_pass',
version: '1.0.0',
username: 'user',
password: 'pass',
compression: 'none',
});

expect(
(utils.getByTestId('settingsOutputsFlyout.kafkaPasswordSecretInput') as any).value
).toEqual('pass');

fireEvent.click(utils.getByText('Save and apply settings'));

await waitFor(() => {
expect(mockSendPutOutput).toHaveBeenCalledWith(
'outputK',
expect.objectContaining({
secrets: { password: 'pass' },
})
);
expect((mockSendPutOutput.mock.calls[0][1] as any).password).toBeUndefined();
});
});

it('should populate secret input with plain text value when editing logstash output', async () => {
jest.spyOn(ExperimentalFeaturesService, 'get').mockReturnValue({ outputSecretsStorage: true });
const { utils } = renderFlyout({
type: 'logstash',
name: 'logstash output',
id: 'outputL',
is_default: false,
is_default_monitoring: false,
hosts: ['logstash'],
ssl: { certificate: 'cert', key: 'key', certificate_authorities: [] },
});

expect((utils.getByTestId('sslKeySecretInput') as HTMLInputElement).value).toEqual('key');

fireEvent.click(utils.getByText('Save and apply settings'));

await waitFor(() => {
expect(mockSendPutOutput).toHaveBeenCalledWith(
'outputL',
expect.objectContaining({
secrets: { ssl: { key: 'key' } },
ssl: { certificate: 'cert', certificate_authorities: [] },
})
);
});
});

it('should show a callout in the flyout if the selected output is logstash and no encrypted key is set', async () => {
mockedUsedFleetStatus.mockReturnValue({
missingOptionalFeatures: ['encrypted_saved_object_encryption_key_required'],
Expand Down Expand Up @@ -214,6 +324,37 @@ describe('EditOutputFlyout', () => {
expect(utils.queryByTestId('serviceTokenSecretInput')).not.toBeNull();
});

it('should populate secret service token input with plain text value when editing remote ES output', async () => {
jest
.spyOn(ExperimentalFeaturesService, 'get')
.mockReturnValue({ remoteESOutput: true, outputSecretsStorage: true });
const { utils } = renderFlyout({
type: 'remote_elasticsearch',
name: 'remote es output',
id: 'outputR',
is_default: false,
is_default_monitoring: false,
service_token: '1234',
hosts: ['https://localhost:9200'],
});

expect((utils.getByTestId('serviceTokenSecretInput') as HTMLInputElement).value).toEqual(
'1234'
);

fireEvent.click(utils.getByText('Save and apply settings'));

await waitFor(() => {
expect(mockSendPutOutput).toHaveBeenCalledWith(
'outputR',
expect.objectContaining({
secrets: { service_token: '1234' },
service_token: undefined,
})
);
});
});

it('should not display remote ES output in type lists if serverless', async () => {
jest.spyOn(ExperimentalFeaturesService, 'get').mockReturnValue({ remoteESOutput: true });
mockUseStartServices.mockReset();
Expand Down
Loading

0 comments on commit 3c7c2f1

Please sign in to comment.