[Cloud Security] use only available agent versions for Cloudformation and Cloud Shell parameters (#166198)

## Summary

fixes 
- https://github.com/elastic/security-team/issues/7557

instead of using Kibana version for Cloudformation and Cloud Shell
params in CNVM and CSPM integrations, check if the version of an agent
that matches the current Kibana version actually available as an
artifact. Relevant for serverless, where Kibana version points to
not-yet released versions of Elastic Agent.

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
This commit is contained in:
Maxim Kholod 2023-09-26 10:28:13 +02:00 committed by GitHub
parent 307234384d
commit 62f9b56c4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 146 additions and 6 deletions

View file

@ -0,0 +1,125 @@
/*
* 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 { renderHook } from '@testing-library/react-hooks';
import { useAgentVersion } from './use_agent_version';
import { useKibanaVersion } from './use_kibana_version';
import { sendGetAgentsAvailableVersions } from './use_request';
jest.mock('./use_kibana_version');
jest.mock('./use_request');
describe('useAgentVersion', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('should return agent version that matches Kibana version if released', async () => {
const mockKibanaVersion = '8.8.1';
const mockAvailableVersions = ['8.9.0', '8.8.1', '8.8.0', '8.7.0'];
(useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion);
(sendGetAgentsAvailableVersions as jest.Mock).mockResolvedValue({
data: { items: mockAvailableVersions },
});
const { result, waitForNextUpdate } = renderHook(() => useAgentVersion());
expect(sendGetAgentsAvailableVersions).toHaveBeenCalled();
await waitForNextUpdate();
expect(result.current).toEqual(mockKibanaVersion);
});
it('should return the latest availeble agent version if a version that matches Kibana version is not released', async () => {
const mockKibanaVersion = '8.11.0';
const mockAvailableVersions = ['8.8.0', '8.7.0', '8.9.2', '7.16.0'];
(useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion);
(sendGetAgentsAvailableVersions as jest.Mock).mockResolvedValue({
data: { items: mockAvailableVersions },
});
const { result, waitForNextUpdate } = renderHook(() => useAgentVersion());
expect(sendGetAgentsAvailableVersions).toHaveBeenCalled();
await waitForNextUpdate();
expect(result.current).toEqual('8.9.2');
});
it('should return the agent version that is <= Kibana version if an agent version that matches Kibana version is not released', async () => {
const mockKibanaVersion = '8.8.3';
const mockAvailableVersions = ['8.8.0', '8.8.1', '8.8.2', '8.7.0', '8.9.2', '7.16.0'];
(useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion);
(sendGetAgentsAvailableVersions as jest.Mock).mockResolvedValue({
data: { items: mockAvailableVersions },
});
const { result, waitForNextUpdate } = renderHook(() => useAgentVersion());
expect(sendGetAgentsAvailableVersions).toHaveBeenCalled();
await waitForNextUpdate();
expect(result.current).toEqual('8.8.2');
});
it('should return the latest availeble agent version if a snapshot version', async () => {
const mockKibanaVersion = '8.10.0-SNAPSHOT';
const mockAvailableVersions = ['8.8.0', '8.7.0', '8.9.2', '7.16.0'];
(useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion);
(sendGetAgentsAvailableVersions as jest.Mock).mockResolvedValue({
data: { items: mockAvailableVersions },
});
const { result, waitForNextUpdate } = renderHook(() => useAgentVersion());
expect(sendGetAgentsAvailableVersions).toHaveBeenCalled();
await waitForNextUpdate();
expect(result.current).toEqual('8.9.2');
});
it('should return kibana version if no agent versions available', async () => {
const mockKibanaVersion = '8.11.0';
const mockAvailableVersions: string[] = [];
(useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion);
(sendGetAgentsAvailableVersions as jest.Mock).mockResolvedValue({
data: { items: mockAvailableVersions },
});
const { result, waitForNextUpdate } = renderHook(() => useAgentVersion());
expect(sendGetAgentsAvailableVersions).toHaveBeenCalled();
await waitForNextUpdate();
expect(result.current).toEqual('8.11.0');
});
it('should return kibana version if the list of available agent versions is not available', async () => {
const mockKibanaVersion = '8.11.0';
(useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion);
(sendGetAgentsAvailableVersions as jest.Mock).mockRejectedValue(new Error('Fetching error'));
const { result, waitForNextUpdate } = renderHook(() => useAgentVersion());
expect(sendGetAgentsAvailableVersions).toHaveBeenCalled();
await waitForNextUpdate();
expect(result.current).toEqual(mockKibanaVersion);
});
});

View file

@ -4,14 +4,15 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { useEffect, useState } from 'react';
import semverRcompare from 'semver/functions/rcompare';
import semverLt from 'semver/functions/lt';
import { useKibanaVersion } from './use_kibana_version';
import { sendGetAgentsAvailableVersions } from './use_request';
/**
* @returns The most recent agent version available to install or upgrade to.
* @returns The most compatible agent version available to install or upgrade to.
*/
export const useAgentVersion = (): string | undefined => {
const kibanaVersion = useKibanaVersion();
@ -21,12 +22,26 @@ export const useAgentVersion = (): string | undefined => {
const getVersions = async () => {
try {
const res = await sendGetAgentsAvailableVersions();
// if the endpoint returns an error, use the fallback versions
const versionsList = res?.data?.items ? res.data.items : [kibanaVersion];
const availableVersions = res?.data?.items;
let agentVersionToUse;
setAgentVersion(versionsList[0]);
if (
availableVersions &&
availableVersions.length > 0 &&
availableVersions.indexOf(kibanaVersion) === -1
) {
availableVersions.sort(semverRcompare);
agentVersionToUse =
availableVersions.find((version) => {
return semverLt(version, kibanaVersion);
}) || availableVersions[0];
} else {
agentVersionToUse = kibanaVersion;
}
setAgentVersion(agentVersionToUse);
} catch (err) {
return;
setAgentVersion(kibanaVersion);
}
};