diff --git a/x-pack/plugins/fleet/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts index dfee7502c4ed1..95e1f07e69749 100644 --- a/x-pack/plugins/fleet/common/types/index.ts +++ b/x-pack/plugins/fleet/common/types/index.ts @@ -16,6 +16,7 @@ import type { export interface FleetConfigType { enabled: boolean; + isAirGapped: boolean; registryUrl?: string; registryProxyUrl?: string; agents: { diff --git a/x-pack/plugins/fleet/server/config.ts b/x-pack/plugins/fleet/server/config.ts index 0a817e0ccbfed..0ab1320650920 100644 --- a/x-pack/plugins/fleet/server/config.ts +++ b/x-pack/plugins/fleet/server/config.ts @@ -126,6 +126,7 @@ export const config: PluginConfigDescriptor = { ], schema: schema.object( { + isAirGapped: schema.maybe(schema.boolean({ defaultValue: false })), registryUrl: schema.maybe(schema.uri({ scheme: ['http', 'https'] })), registryProxyUrl: schema.maybe(schema.uri({ scheme: ['http', 'https'] })), agents: schema.object({ diff --git a/x-pack/plugins/fleet/server/services/agents/versions.test.ts b/x-pack/plugins/fleet/server/services/agents/versions.test.ts index 15fa38d4949bc..9f8a5091e3ee2 100644 --- a/x-pack/plugins/fleet/server/services/agents/versions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/versions.test.ts @@ -8,9 +8,15 @@ import { readFile } from 'fs/promises'; import fetch from 'node-fetch'; +import type { DeepPartial } from 'utility-types'; + +import type { FleetConfigType } from '../../../public/plugin'; + +import { getAvailableVersions } from './versions'; let mockKibanaVersion = '300.0.0'; -let mockConfig = {}; +let mockConfig: DeepPartial = {}; + jest.mock('../app_context', () => { const { loggerMock } = jest.requireActual('@kbn/logging-mocks'); return { @@ -33,8 +39,6 @@ const emptyResponse = { text: jest.fn().mockResolvedValue(JSON.stringify({})), } as any; -import { getAvailableVersions } from './versions'; - describe('getAvailableVersions', () => { beforeEach(() => { mockedReadFile.mockReset(); @@ -204,4 +208,15 @@ describe('getAvailableVersions', () => { // Should sort, uniquify and filter out versions < 7.17 expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']); }); + + it('should not fetch from product versions API when air-gapped config is set', async () => { + mockKibanaVersion = '300.0.0'; + mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`); + + mockConfig = { isAirGapped: true }; + const res = await getAvailableVersions({ ignoreCache: true }); + + expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']); + expect(mockedFetch).not.toBeCalled(); + }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/versions.ts b/x-pack/plugins/fleet/server/services/agents/versions.ts index b5a09bc99e2cb..39941e2d38fc9 100644 --- a/x-pack/plugins/fleet/server/services/agents/versions.ts +++ b/x-pack/plugins/fleet/server/services/agents/versions.ts @@ -111,6 +111,11 @@ export const getAvailableVersions = async ({ }; async function fetchAgentVersionsFromApi() { + // If the airgapped flag is set, do not attempt to reach out to the product versions API + if (appContextService.getConfig()?.isAirGapped) { + return []; + } + const logger = appContextService.getLogger(); const options = {