[Fleet] Add xpack.fleet.isAirGapped flag (#174214)

## Summary

Closes https://github.com/elastic/kibana/issues/173125

Adds a new `xpack.fleet.isAirGapped` flag to `kibana.yml` that allow
users in air-gapped environments to inform Fleet that it should "fail
fast" and skip unnecessary requests that won't be possible as Kibana
doesn't have internet access.

This PR also uses the new flag to skip the API request to the
`product_versions` API if the airgapped flag is set to true. There are
probably other places we could use this flag in a similar way, but they
can be handled separately from this PR.

### Checklist

Delete any items that are not applicable to this PR.

- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [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:
Kyle Pollich 2024-01-04 09:22:20 -05:00 committed by GitHub
parent 1417fd37f5
commit 7a613fb6cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 3 deletions

View file

@ -24,6 +24,8 @@ See the {fleet-guide}/index.html[{fleet}] docs for more information about {fleet
`xpack.fleet.agents.enabled` {ess-icon}::
Set to `true` (default) to enable {fleet}.
`xpack.fleet.isAirGapped`::
Set to `true` to indicate {fleet} is running in an air-gapped environment. Refer to {fleet-guide}/air-gapped.html[Air-gapped environments] for details. Enabling this flag helps Fleet skip needless requests and improve the user experience for air-gapped environments.
[[fleet-data-visualizer-settings]]

View file

@ -16,6 +16,7 @@ import type {
export interface FleetConfigType {
enabled: boolean;
isAirGapped?: boolean;
registryUrl?: string;
registryProxyUrl?: string;
agents: {

View file

@ -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({

View file

@ -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<FleetConfigType> = {};
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();
});
});

View file

@ -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 = {