[Fleet] remove bwc code (#118164) (#118343)

* remove bwc code

* cleanup of old agent SOs

* fixed tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Julia Bardi <90178898+juliaElastic@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2021-11-11 10:30:08 -05:00 committed by GitHub
parent bb241e3e8b
commit 7ed19d7696
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 137 additions and 1080 deletions

View file

@ -84,11 +84,26 @@ Object {
"type": "file-upload-telemetry",
},
},
Object {
"term": Object {
"type": "fleet-agent-actions",
},
},
Object {
"term": Object {
"type": "fleet-agent-events",
},
},
Object {
"term": Object {
"type": "fleet-agents",
},
},
Object {
"term": Object {
"type": "fleet-enrollment-api-keys",
},
},
Object {
"term": Object {
"type": "ml-telemetry",
@ -225,11 +240,26 @@ Object {
"type": "file-upload-telemetry",
},
},
Object {
"term": Object {
"type": "fleet-agent-actions",
},
},
Object {
"term": Object {
"type": "fleet-agent-events",
},
},
Object {
"term": Object {
"type": "fleet-agents",
},
},
Object {
"term": Object {
"type": "fleet-enrollment-api-keys",
},
},
Object {
"term": Object {
"type": "ml-telemetry",
@ -370,11 +400,26 @@ Object {
"type": "file-upload-telemetry",
},
},
Object {
"term": Object {
"type": "fleet-agent-actions",
},
},
Object {
"term": Object {
"type": "fleet-agent-events",
},
},
Object {
"term": Object {
"type": "fleet-agents",
},
},
Object {
"term": Object {
"type": "fleet-enrollment-api-keys",
},
},
Object {
"term": Object {
"type": "ml-telemetry",
@ -519,11 +564,26 @@ Object {
"type": "file-upload-telemetry",
},
},
Object {
"term": Object {
"type": "fleet-agent-actions",
},
},
Object {
"term": Object {
"type": "fleet-agent-events",
},
},
Object {
"term": Object {
"type": "fleet-agents",
},
},
Object {
"term": Object {
"type": "fleet-enrollment-api-keys",
},
},
Object {
"term": Object {
"type": "ml-telemetry",
@ -705,11 +765,26 @@ Object {
"type": "file-upload-telemetry",
},
},
Object {
"term": Object {
"type": "fleet-agent-actions",
},
},
Object {
"term": Object {
"type": "fleet-agent-events",
},
},
Object {
"term": Object {
"type": "fleet-agents",
},
},
Object {
"term": Object {
"type": "fleet-enrollment-api-keys",
},
},
Object {
"term": Object {
"type": "ml-telemetry",
@ -857,11 +932,26 @@ Object {
"type": "file-upload-telemetry",
},
},
Object {
"term": Object {
"type": "fleet-agent-actions",
},
},
Object {
"term": Object {
"type": "fleet-agent-events",
},
},
Object {
"term": Object {
"type": "fleet-agents",
},
},
Object {
"term": Object {
"type": "fleet-enrollment-api-keys",
},
},
Object {
"term": Object {
"type": "ml-telemetry",

View file

@ -18,6 +18,10 @@ export const REMOVED_TYPES: string[] = [
'file-upload-telemetry',
// https://github.com/elastic/kibana/issues/91869
'fleet-agent-events',
// https://github.com/elastic/obs-dc-team/issues/334
'fleet-agents',
'fleet-agent-actions',
'fleet-enrollment-api-keys',
// Was removed in 7.12
'ml-telemetry',
'server',

View file

@ -5,8 +5,7 @@
* 2.0.
*/
export const AGENT_SAVED_OBJECT_TYPE = 'fleet-agents';
export const AGENT_ACTION_SAVED_OBJECT_TYPE = 'fleet-agent-actions';
export const AGENTS_PREFIX = 'fleet-agents';
export const AGENT_TYPE_PERMANENT = 'PERMANENT';
export const AGENT_TYPE_EPHEMERAL = 'EPHEMERAL';

View file

@ -5,6 +5,4 @@
* 2.0.
*/
export const ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE = 'fleet-enrollment-api-keys';
export const ENROLLMENT_API_KEYS_INDEX = '.fleet-enrollment-api-keys';

View file

@ -12,7 +12,6 @@ export const EPM_API_ROOT = `${API_ROOT}/epm`;
export const DATA_STREAM_API_ROOT = `${API_ROOT}/data_streams`;
export const PACKAGE_POLICY_API_ROOT = `${API_ROOT}/package_policies`;
export const AGENT_POLICY_API_ROOT = `${API_ROOT}/agent_policies`;
export const FLEET_API_ROOT_7_9 = `/api/ingest_manager/fleet`;
export const LIMITED_CONCURRENCY_ROUTE_TAG = 'ingest:limited-concurrency';

View file

@ -66,15 +66,6 @@ export interface AgentPolicyAction extends NewAgentAction {
ack_data?: any;
}
// Make policy change action renaming BWC with agent version <= 7.9
// eslint-disable-next-line @typescript-eslint/naming-convention
export type AgentPolicyActionV7_9 = Omit<AgentPolicyAction, 'type' | 'data'> & {
type: 'CONFIG_CHANGE';
data: {
config: FullAgentPolicy;
};
};
interface CommonAgentActionSOAttributes {
type: AgentActionType;
sent_at?: string;

View file

@ -37,8 +37,6 @@ All of the code that interacts with this index is currently located in
[`x-pack/plugins/fleet/server/services/agents/crud.ts`](../server/services/agents/crud.ts) and the schema of these
documents is maintained by the `FleetServerAgent` TypeScript interface.
Prior to Fleet Server, this data was stored in the `fleet-agents` Saved Object type which is now obsolete.
### `.fleet-actions` index
Each document in this index represents an action that was initiated by a user and needs to be processed by Fleet Server
@ -167,46 +165,3 @@ represents the relative file path of the file from the package contents
Used as "tombstone record" to indicate that a package that was installed by default through preconfiguration was
explicitly deleted by user. Used to avoid recreating a preconfiguration policy that a user explicitly does not want.
### `fleet-agents`
**DEPRECATED in favor of `.fleet-agents` index.**
- Constant in code: `AGENT_SAVED_OBJECT_TYPE`
- Introduced in ?
- [Code Link](../server/saved_objects/index.ts#76)
- Migrations: 7.10.0, 7.12.0
- References to other objects:
- `policy_id` - ID that points to the policy (`ingest-agent-policies`) this agent is assigned to.
- `access_api_key_id`
- `default_api_key_id`
Tracks an individual Elastic Agent's enrollment in the Fleet, which policy it is current assigned to, its check in
status, which packages are currently installed, and other metadata about the Agent.
### `fleet-agent-actions`
**DEPRECATED in favor of `.fleet-agent-actions` index.**
- Constant in code: `AGENT_ACTION_SAVED_OBJECT_TYPE`
- Introduced in ?
- [Code Link](../server/saved_objects/index.ts#113)
- Migrations: 7.10.0
- References to other objects:
- `agent_id` - ID that points to the agent for this action (`fleet-agents`)
- `policy_id`- ID that points to the policy for this action (`ingest-agent-policies`)
### `fleet-enrollment-api-keys`
**DEPRECATED in favor of `.fleet-enrollment-api-keys` index.**
- Constant in code: `ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE`
- Introduced in ?
- [Code Link](../server/saved_objects/index.ts#166)
- Migrations: 7.10.0
- References to other objects:
- `api_key_id`
- `policy_id` - ID that points to an agent policy (`ingest-agent-policies`)
Contains an enrollment key that can be used to enroll a new agent in a specific agent policy.

View file

@ -12,9 +12,9 @@ import { fromKueryExpression } from '@kbn/es-query';
import type { IFieldType } from '../../../../../../../src/plugins/data/public';
import { QueryStringInput } from '../../../../../../../src/plugins/data/public';
import { useStartServices } from '../hooks';
import { INDEX_NAME, AGENT_SAVED_OBJECT_TYPE } from '../constants';
import { INDEX_NAME, AGENTS_PREFIX } from '../constants';
const HIDDEN_FIELDS = [`${AGENT_SAVED_OBJECT_TYPE}.actions`, '_id', '_index'];
const HIDDEN_FIELDS = [`${AGENTS_PREFIX}.actions`, '_id', '_index'];
interface Props {
value: string;

View file

@ -10,7 +10,7 @@ import { EuiConfirmModal, EuiCallOut } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { AGENT_SAVED_OBJECT_TYPE } from '../../../constants';
import { AGENTS_PREFIX } from '../../../constants';
import { sendDeleteAgentPolicy, useStartServices, useConfig, sendRequest } from '../../../hooks';
interface Props {
@ -98,7 +98,7 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent<Props> = ({ chil
path: `/api/fleet/agents`,
method: 'get',
query: {
kuery: `${AGENT_SAVED_OBJECT_TYPE}.policy_id : ${agentPolicyToCheck}`,
kuery: `${AGENTS_PREFIX}.policy_id : ${agentPolicyToCheck}`,
},
});
setAgentsCount(data?.total || 0);

View file

@ -42,7 +42,7 @@ import {
ContextMenuActions,
} from '../../../components';
import { AgentStatusKueryHelper, isAgentUpgradeable } from '../../../services';
import { AGENT_SAVED_OBJECT_TYPE, FLEET_SERVER_PACKAGE } from '../../../constants';
import { AGENTS_PREFIX, FLEET_SERVER_PACKAGE } from '../../../constants';
import {
AgentReassignAgentPolicyModal,
AgentHealth,
@ -207,7 +207,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
if (kueryBuilder) {
kueryBuilder = `(${kueryBuilder}) and`;
}
kueryBuilder = `${kueryBuilder} ${AGENT_SAVED_OBJECT_TYPE}.policy_id : (${selectedAgentPolicies
kueryBuilder = `${kueryBuilder} ${AGENTS_PREFIX}.policy_id : (${selectedAgentPolicies
.map((agentPolicy) => `"${agentPolicy}"`)
.join(' or ')})`;
}

View file

@ -11,7 +11,7 @@ import type { EuiLinkAnchorProps } from '@elastic/eui';
import { EuiLink } from '@elastic/eui';
import { useLink } from '../hooks';
import { AGENT_SAVED_OBJECT_TYPE } from '../constants';
import { AGENTS_PREFIX } from '../constants';
/**
* Displays the provided `count` number as a link to the Agents list if it is greater than zero
@ -37,7 +37,7 @@ export const LinkedAgentCount = memo<
<EuiLink
{...otherEuiLinkProps}
href={getHref('agent_list', {
kuery: `${AGENT_SAVED_OBJECT_TYPE}.policy_id : ${agentPolicyId}`,
kuery: `${AGENTS_PREFIX}.policy_id : ${agentPolicyId}`,
})}
>
{displayValue}

View file

@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { useStartServices, sendRequest, sendDeletePackagePolicy, useConfig } from '../hooks';
import { AGENT_API_ROUTES, AGENT_SAVED_OBJECT_TYPE } from '../../common/constants';
import { AGENT_API_ROUTES, AGENTS_PREFIX } from '../../common/constants';
import type { AgentPolicy } from '../types';
interface Props {
@ -53,7 +53,7 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent<Props> = ({
query: {
page: 1,
perPage: 1,
kuery: `${AGENT_SAVED_OBJECT_TYPE}.policy_id : ${agentPolicy.id}`,
kuery: `${AGENTS_PREFIX}.policy_id : ${agentPolicy.id}`,
},
});
setAgentsCount(data?.total || 0);

View file

@ -12,8 +12,7 @@ export {
AGENT_API_ROUTES,
SO_SEARCH_LIMIT,
AGENT_POLICY_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
AGENTS_PREFIX,
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
FLEET_SERVER_PACKAGE,
// Fleet Server index

View file

@ -9,7 +9,6 @@ import type { SavedObjectsClient, ElasticsearchClient } from 'kibana/server';
import type { FleetConfigType } from '../../common/types';
import * as AgentService from '../services/agents';
import { isFleetServerSetup } from '../services/fleet_server';
export interface AgentUsage {
total_enrolled: number;
@ -26,7 +25,7 @@ export const getAgentUsage = async (
esClient?: ElasticsearchClient
): Promise<AgentUsage> => {
// TODO: unsure if this case is possible at all.
if (!soClient || !esClient || !(await isFleetServerSetup())) {
if (!soClient || !esClient) {
return {
total_enrolled: 0,
healthy: 0,

View file

@ -10,7 +10,6 @@ import type { SavedObjectsClient, ElasticsearchClient } from 'kibana/server';
import { packagePolicyService, settingsService } from '../services';
import { getAgentStatusForAgentPolicy } from '../services/agents';
import { isFleetServerSetup } from '../services/fleet_server';
const DEFAULT_USAGE = {
total_all_statuses: 0,
@ -36,7 +35,7 @@ export const getFleetServerUsage = async (
soClient?: SavedObjectsClient,
esClient?: ElasticsearchClient
): Promise<any> => {
if (!soClient || !esClient || !(await isFleetServerSetup())) {
if (!soClient || !esClient) {
return DEFAULT_USAGE;
}

View file

@ -35,14 +35,12 @@ export {
PRECONFIGURATION_API_ROUTES,
// Saved object types
SO_SEARCH_LIMIT,
AGENT_SAVED_OBJECT_TYPE,
AGENT_ACTION_SAVED_OBJECT_TYPE,
AGENTS_PREFIX,
AGENT_POLICY_SAVED_OBJECT_TYPE,
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
OUTPUT_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
ASSETS_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
// Defaults
DEFAULT_AGENT_POLICY,

View file

@ -1,86 +0,0 @@
/*
* 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 { applyDeprecations, configDeprecationFactory } from '@kbn/config';
import { configDeprecationsMock } from '../../../../src/core/server/mocks';
import { config } from '.';
const deprecationContext = configDeprecationsMock.createContext();
const applyConfigDeprecations = (settings: Record<string, any> = {}) => {
if (!config.deprecations) {
throw new Error('Config is not valid no deprecations');
}
const deprecations = config.deprecations(configDeprecationFactory);
const deprecationMessages: string[] = [];
const migrated = applyDeprecations(
settings,
deprecations.map((deprecation) => ({
deprecation,
path: '',
context: deprecationContext,
})),
() =>
({ message }) =>
deprecationMessages.push(message)
);
return {
messages: deprecationMessages,
migrated: migrated.config,
};
};
describe('Config depreciation test', () => {
it('should migrate old xpack.ingestManager.fleet settings to xpack.fleet.agents', () => {
const { migrated } = applyConfigDeprecations({
xpack: {
ingestManager: {
fleet: { enabled: true, elasticsearch: { host: 'http://testes.fr:9200' } },
},
},
});
expect(migrated).toMatchInlineSnapshot(`
Object {
"xpack": Object {
"fleet": Object {
"agents": Object {
"elasticsearch": Object {
"hosts": Array [
"http://testes.fr:9200",
],
},
"enabled": true,
},
},
},
}
`);
});
it('should support mixing xpack.ingestManager config and xpack.fleet config', () => {
const { migrated } = applyConfigDeprecations({
xpack: {
ingestManager: { registryUrl: 'http://registrytest.fr' },
fleet: { registryProxyUrl: 'http://registryProxy.fr' },
},
});
expect(migrated).toMatchInlineSnapshot(`
Object {
"xpack": Object {
"fleet": Object {
"registryProxyUrl": "http://registryProxy.fr",
"registryUrl": "http://registrytest.fr",
},
},
}
`);
});
});

View file

@ -44,52 +44,6 @@ export const config: PluginConfigDescriptor = {
agents: true,
},
deprecations: ({ renameFromRoot, unused, unusedFromRoot }) => [
// Fleet plugin was named ingestManager before
renameFromRoot('xpack.ingestManager.enabled', 'xpack.fleet.enabled', { level: 'critical' }),
renameFromRoot('xpack.ingestManager.registryUrl', 'xpack.fleet.registryUrl', {
level: 'critical',
}),
renameFromRoot('xpack.ingestManager.registryProxyUrl', 'xpack.fleet.registryProxyUrl', {
level: 'critical',
}),
renameFromRoot('xpack.ingestManager.fleet', 'xpack.ingestManager.agents', {
level: 'critical',
}),
renameFromRoot('xpack.ingestManager.agents.enabled', 'xpack.fleet.agents.enabled', {
level: 'critical',
}),
renameFromRoot('xpack.ingestManager.agents.elasticsearch', 'xpack.fleet.agents.elasticsearch', {
level: 'critical',
}),
renameFromRoot(
'xpack.ingestManager.agents.tlsCheckDisabled',
'xpack.fleet.agents.tlsCheckDisabled',
{ level: 'critical' }
),
renameFromRoot(
'xpack.ingestManager.agents.pollingRequestTimeout',
'xpack.fleet.agents.pollingRequestTimeout',
{ level: 'critical' }
),
renameFromRoot(
'xpack.ingestManager.agents.maxConcurrentConnections',
'xpack.fleet.agents.maxConcurrentConnections',
{ level: 'critical' }
),
renameFromRoot('xpack.ingestManager.agents.kibana', 'xpack.fleet.agents.kibana', {
level: 'critical',
}),
renameFromRoot(
'xpack.ingestManager.agents.agentPolicyRolloutRateLimitIntervalMs',
'xpack.fleet.agents.agentPolicyRolloutRateLimitIntervalMs',
{ level: 'critical' }
),
renameFromRoot(
'xpack.ingestManager.agents.agentPolicyRolloutRateLimitRequestPerInterval',
'xpack.fleet.agents.agentPolicyRolloutRateLimitRequestPerInterval',
{ level: 'critical' }
),
unusedFromRoot('xpack.ingestManager', { level: 'critical' }),
// Unused settings before Fleet server exists
unused('agents.kibana', { level: 'critical' }),
unused('agents.maxConcurrentConnections', { level: 'critical' }),

View file

@ -30,7 +30,7 @@ function createXPackRoot(config: {} = {}) {
});
}
describe('ingestManager', () => {
describe('fleet', () => {
describe('default. manager, EPM, and Fleet all disabled', () => {
let root: ReturnType<typeof kbnTestServer.createRoot>;
@ -64,11 +64,11 @@ describe('ingestManager', () => {
let root: ReturnType<typeof kbnTestServer.createRoot>;
beforeAll(async () => {
const ingestManagerConfig = {
const fleetConfig = {
enabled: true,
};
root = createXPackRoot({
ingestManager: ingestManagerConfig,
fleet: fleetConfig,
});
await root.preboot();
await root.setup();
@ -103,12 +103,12 @@ describe('ingestManager', () => {
let root: ReturnType<typeof kbnTestServer.createRoot>;
beforeAll(async () => {
const ingestManagerConfig = {
const fleetConfig = {
enabled: true,
epm: { enabled: true },
};
root = createXPackRoot({
ingestManager: ingestManagerConfig,
fleet: fleetConfig,
});
await root.preboot();
await root.setup();
@ -138,12 +138,12 @@ describe('ingestManager', () => {
let root: ReturnType<typeof kbnTestServer.createRoot>;
beforeAll(async () => {
const ingestManagerConfig = {
const fleetConfig = {
enabled: true,
fleet: { enabled: true },
};
root = createXPackRoot({
ingestManager: ingestManagerConfig,
fleet: fleetConfig,
});
await root.preboot();
await root.setup();
@ -173,13 +173,13 @@ describe('ingestManager', () => {
let root: ReturnType<typeof kbnTestServer.createRoot>;
beforeAll(async () => {
const ingestManagerConfig = {
const fleetConfig = {
enabled: true,
epm: { enabled: true },
fleet: { enabled: true },
};
root = createXPackRoot({
ingestManager: ingestManagerConfig,
fleet: fleetConfig,
});
await root.preboot();
await root.setup();

View file

@ -40,8 +40,6 @@ import {
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
ASSETS_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE,
} from './constants';
import { registerSavedObjects, registerEncryptedSavedObjects } from './saved_objects';
@ -82,7 +80,6 @@ import {
import { registerFleetUsageCollector } from './collectors/register';
import { getInstallation, ensureInstalledPackage } from './services/epm/packages';
import { RouterWrappers } from './routes/security';
import { startFleetServerSetup } from './services/fleet_server';
import { FleetArtifactsClient } from './services/artifacts';
import type { FleetRouter } from './types/request_context';
import { TelemetryEventsSender } from './telemetry/sender';
@ -131,8 +128,6 @@ const allSavedObjectTypes = [
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
ASSETS_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE,
];
@ -335,15 +330,10 @@ export class FleetPlugin
});
licenseService.start(this.licensing$);
const fleetServerSetup = startFleetServerSetup();
this.telemetryEventsSender.start(plugins.telemetry, core);
return {
fleetSetupCompleted: () =>
new Promise<void>((resolve) => {
Promise.all([fleetServerSetup]).finally(() => resolve());
}),
fleetSetupCompleted: () => Promise.resolve(),
esIndexPatternService: new ESIndexPatternSavedObjectService(),
packageService: {
getInstallation,

View file

@ -13,7 +13,7 @@ import { safeDump } from 'js-yaml';
import { fullAgentPolicyToYaml } from '../../../common/services';
import { appContextService, agentPolicyService, packagePolicyService } from '../../services';
import { getAgentsByKuery } from '../../services/agents';
import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { AGENTS_PREFIX } from '../../constants';
import type {
GetAgentPoliciesRequestSchema,
GetOneAgentPolicyRequestSchema,
@ -64,7 +64,7 @@ export const getAgentPoliciesHandler: RequestHandler<
showInactive: false,
perPage: 0,
page: 1,
kuery: `${AGENT_SAVED_OBJECT_TYPE}.policy_id:${agentPolicy.id}`,
kuery: `${AGENTS_PREFIX}.policy_id:${agentPolicy.id}`,
}).then(({ total: agentTotal }) => (agentPolicy.agents = agentTotal)),
{ concurrency: 10 }
);

View file

@ -14,29 +14,19 @@ import {
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
ASSETS_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
AGENT_ACTION_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE,
} from '../constants';
import {
migrateAgentActionToV7100,
migrateAgentPolicyToV7100,
migrateAgentToV7100,
migrateEnrollmentApiKeysToV7100,
migratePackagePolicyToV7100,
migrateSettingsToV7100,
} from './migrations/to_v7_10_0';
import { migratePackagePolicyToV7110 } from './migrations/to_v7_11_0';
import {
migrateAgentPolicyToV7120,
migrateAgentToV7120,
migratePackagePolicyToV7120,
} from './migrations/to_v7_12_0';
import { migrateAgentPolicyToV7120, migratePackagePolicyToV7120 } from './migrations/to_v7_12_0';
import {
migratePackagePolicyToV7130,
migrateSettingsToV7130,
@ -75,66 +65,6 @@ const getSavedObjectTypes = (
'7.13.0': migrateSettingsToV7130,
},
},
[AGENT_SAVED_OBJECT_TYPE]: {
name: AGENT_SAVED_OBJECT_TYPE,
hidden: false,
namespaceType: 'agnostic',
management: {
importableAndExportable: false,
},
mappings: {
properties: {
type: { type: 'keyword' },
active: { type: 'boolean' },
enrolled_at: { type: 'date' },
unenrolled_at: { type: 'date' },
unenrollment_started_at: { type: 'date' },
upgraded_at: { type: 'date' },
upgrade_started_at: { type: 'date' },
access_api_key_id: { type: 'keyword' },
version: { type: 'keyword' },
user_provided_metadata: { type: 'flattened' },
local_metadata: { type: 'flattened' },
policy_id: { type: 'keyword' },
policy_revision: { type: 'integer' },
last_updated: { type: 'date' },
last_checkin: { type: 'date' },
last_checkin_status: { type: 'keyword' },
default_api_key_id: { type: 'keyword' },
default_api_key: { type: 'binary' },
updated_at: { type: 'date' },
current_error_events: { type: 'text', index: false },
packages: { type: 'keyword' },
},
},
migrations: {
'7.10.0': migrateAgentToV7100,
'7.12.0': migrateAgentToV7120,
},
},
[AGENT_ACTION_SAVED_OBJECT_TYPE]: {
name: AGENT_ACTION_SAVED_OBJECT_TYPE,
hidden: false,
namespaceType: 'agnostic',
management: {
importableAndExportable: false,
},
mappings: {
properties: {
agent_id: { type: 'keyword' },
policy_id: { type: 'keyword' },
policy_revision: { type: 'integer' },
type: { type: 'keyword' },
data: { type: 'binary' },
ack_data: { type: 'text' },
sent_at: { type: 'date' },
created_at: { type: 'date' },
},
},
migrations: {
'7.10.0': migrateAgentActionToV7100(encryptedSavedObjects),
},
},
[AGENT_POLICY_SAVED_OBJECT_TYPE]: {
name: AGENT_POLICY_SAVED_OBJECT_TYPE,
hidden: false,
@ -167,30 +97,6 @@ const getSavedObjectTypes = (
'7.12.0': migrateAgentPolicyToV7120,
},
},
[ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE]: {
name: ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
hidden: false,
namespaceType: 'agnostic',
management: {
importableAndExportable: false,
},
mappings: {
properties: {
name: { type: 'keyword' },
type: { type: 'keyword' },
api_key: { type: 'binary' },
api_key_id: { type: 'keyword' },
policy_id: { type: 'keyword' },
created_at: { type: 'date' },
updated_at: { type: 'date' },
expire_at: { type: 'date' },
active: { type: 'boolean' },
},
},
migrations: {
'7.10.0': migrateEnrollmentApiKeysToV7100,
},
},
[OUTPUT_SAVED_OBJECT_TYPE]: {
name: OUTPUT_SAVED_OBJECT_TYPE,
hidden: false,
@ -399,48 +305,4 @@ export function registerEncryptedSavedObjects(
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
) {
// Encrypted saved objects
encryptedSavedObjects.registerType({
type: ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
attributesToEncrypt: new Set(['api_key']),
attributesToExcludeFromAAD: new Set([
'name',
'type',
'api_key_id',
'policy_id',
'created_at',
'updated_at',
'expire_at',
'active',
]),
});
encryptedSavedObjects.registerType({
type: AGENT_SAVED_OBJECT_TYPE,
attributesToEncrypt: new Set(['default_api_key']),
attributesToExcludeFromAAD: new Set([
'type',
'active',
'enrolled_at',
'access_api_key_id',
'version',
'user_provided_metadata',
'local_metadata',
'policy_id',
'policy_revision',
'last_updated',
'last_checkin',
'last_checkin_status',
'updated_at',
'current_error_events',
'unenrolled_at',
'unenrollment_started_at',
'packages',
'upgraded_at',
'upgrade_started_at',
]),
});
encryptedSavedObjects.registerType({
type: AGENT_ACTION_SAVED_OBJECT_TYPE,
attributesToEncrypt: new Set(['data']),
attributesToExcludeFromAAD: new Set(['agent_id', 'type', 'sent_at', 'created_at']),
});
}

View file

@ -5,33 +5,9 @@
* 2.0.
*/
import type { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'kibana/server';
import type { SavedObjectMigrationFn } from 'kibana/server';
import type { EncryptedSavedObjectsPluginSetup } from '../../../../encrypted_saved_objects/server';
import type {
Agent,
AgentPolicy,
PackagePolicy,
EnrollmentAPIKey,
Settings,
AgentAction,
} from '../../types';
export const migrateAgentToV7100: SavedObjectMigrationFn<
Exclude<Agent, 'policy_id' | 'policy_revision'> & {
config_id?: string;
config_revision?: number | null;
},
Agent
> = (agentDoc) => {
agentDoc.attributes.policy_id = agentDoc.attributes.config_id;
delete agentDoc.attributes.config_id;
agentDoc.attributes.policy_revision = agentDoc.attributes.config_revision;
delete agentDoc.attributes.config_revision;
return agentDoc;
};
import type { AgentPolicy, PackagePolicy, Settings } from '../../types';
export const migrateAgentPolicyToV7100: SavedObjectMigrationFn<
Exclude<AgentPolicy, 'package_policies'> & {
@ -46,18 +22,6 @@ export const migrateAgentPolicyToV7100: SavedObjectMigrationFn<
return agentPolicyDoc;
};
export const migrateEnrollmentApiKeysToV7100: SavedObjectMigrationFn<
Exclude<EnrollmentAPIKey, 'policy_id'> & {
config_id?: string;
},
EnrollmentAPIKey
> = (enrollmentApiKeyDoc) => {
enrollmentApiKeyDoc.attributes.policy_id = enrollmentApiKeyDoc.attributes.config_id;
delete enrollmentApiKeyDoc.attributes.config_id;
return enrollmentApiKeyDoc;
};
export const migratePackagePolicyToV7100: SavedObjectMigrationFn<
Exclude<PackagePolicy, 'policy_id'> & {
config_id: string;
@ -84,45 +48,3 @@ export const migrateSettingsToV7100: SavedObjectMigrationFn<
return settingsDoc;
};
export const migrateAgentActionToV7100 = (
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
): SavedObjectMigrationFn<AgentAction, AgentAction> => {
return encryptedSavedObjects.createMigration({
isMigrationNeededPredicate: (
agentActionDoc
): agentActionDoc is SavedObjectUnsanitizedDoc<AgentAction> => {
// @ts-expect-error
return agentActionDoc.attributes.type === 'CONFIG_CHANGE';
},
migration: (agentActionDoc) => {
let agentActionData;
try {
agentActionData = agentActionDoc.attributes.data
? JSON.parse(agentActionDoc.attributes.data)
: undefined;
} catch (e) {
// Silently swallow JSON parsing error
}
if (agentActionData && agentActionData.config) {
const {
attributes: { data, ...restOfAttributes },
} = agentActionDoc;
const { config, ...restOfData } = agentActionData;
return {
...agentActionDoc,
attributes: {
...restOfAttributes,
type: 'POLICY_CHANGE',
data: JSON.stringify({
...restOfData,
policy: config,
}),
},
};
} else {
return agentActionDoc;
}
},
});
};

View file

@ -7,18 +7,10 @@
import type { SavedObjectMigrationFn } from 'kibana/server';
import type { Agent, AgentPolicy } from '../../types';
import type { AgentPolicy } from '../../types';
export { migratePackagePolicyToV7120 } from './security_solution/to_v7_12_0';
export const migrateAgentToV7120: SavedObjectMigrationFn<Agent & { shared_id?: string }, Agent> = (
agentDoc
) => {
delete agentDoc.attributes.shared_id;
return agentDoc;
};
export const migrateAgentPolicyToV7120: SavedObjectMigrationFn<
Exclude<AgentPolicy, 'is_managed' & 'is_default_fleet_server'>,
AgentPolicy

View file

@ -20,7 +20,7 @@ import { SavedObjectsErrorHelpers } from '../../../../../src/core/server';
import type { AuthenticatedUser } from '../../../security/server';
import {
AGENT_POLICY_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
AGENTS_PREFIX,
PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE,
} from '../constants';
import type {
@ -626,7 +626,7 @@ class AgentPolicyService {
showInactive: false,
perPage: 0,
page: 1,
kuery: `${AGENT_SAVED_OBJECT_TYPE}.policy_id:${id}`,
kuery: `${AGENTS_PREFIX}.policy_id:${id}`,
});
if (total > 0) {

View file

@ -16,7 +16,7 @@ import type { AgentSOAttributes, Agent, BulkActionResult, ListWithKuery } from '
import { appContextService, agentPolicyService } from '../../services';
import type { FleetServerAgent } from '../../../common';
import { isAgentUpgradeable, SO_SEARCH_LIMIT } from '../../../common';
import { AGENT_SAVED_OBJECT_TYPE, AGENTS_INDEX } from '../../constants';
import { AGENTS_PREFIX, AGENTS_INDEX } from '../../constants';
import { escapeSearchQueryPhrase, normalizeKuery } from '../saved_object';
import { IngestManagerError, isESClientError, AgentNotFoundError } from '../../errors';
@ -176,7 +176,7 @@ export async function countInactiveAgents(
const filters = [INACTIVE_AGENT_CONDITION];
if (kuery && kuery !== '') {
filters.push(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery));
filters.push(normalizeKuery(AGENTS_PREFIX, kuery));
}
const kueryNode = _joinFilters(filters);

View file

@ -1,255 +0,0 @@
/*
* 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 Boom from '@hapi/boom';
import type { SavedObjectsBulkUpdateObject, SavedObjectsClientContract } from 'src/core/server';
import type { KueryNode } from '@kbn/es-query';
import { fromKueryExpression } from '@kbn/es-query';
import { isAgentUpgradeable } from '../../../common';
import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types';
import { escapeSearchQueryPhrase, normalizeKuery, findAllSOs } from '../saved_object';
import { appContextService } from '../../services';
import { savedObjectToAgent } from './saved_objects';
const ACTIVE_AGENT_CONDITION = `${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`;
const INACTIVE_AGENT_CONDITION = `NOT (${ACTIVE_AGENT_CONDITION})`;
function _joinFilters(filters: Array<string | undefined | KueryNode>) {
return filters
.filter((filter) => filter !== undefined)
.reduce(
(
acc: KueryNode | undefined,
kuery: string | KueryNode | undefined
): KueryNode | undefined => {
if (kuery === undefined) {
return acc;
}
const kueryNode: KueryNode =
typeof kuery === 'string'
? fromKueryExpression(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery))
: kuery;
if (!acc) {
return kueryNode;
}
return {
type: 'function',
function: 'and',
arguments: [acc, kueryNode],
};
},
undefined as KueryNode | undefined
);
}
export async function listAgents(
soClient: SavedObjectsClientContract,
options: ListWithKuery & {
showInactive: boolean;
}
): Promise<{
agents: Agent[];
total: number;
page: number;
perPage: number;
}> {
const {
page = 1,
perPage = 20,
sortField = 'enrolled_at',
sortOrder = 'desc',
kuery,
showInactive = false,
showUpgradeable,
} = options;
const filters: Array<string | KueryNode | undefined> = [];
if (kuery && kuery !== '') {
filters.push(kuery);
}
if (showInactive === false) {
filters.push(ACTIVE_AGENT_CONDITION);
}
try {
let { saved_objects: agentSOs, total } = await soClient.find<AgentSOAttributes>({
type: AGENT_SAVED_OBJECT_TYPE,
filter: _joinFilters(filters) || '',
sortField,
sortOrder,
page,
perPage,
});
// filtering for a range on the version string will not work,
// nor does filtering on a flattened field (local_metadata), so filter here
if (showUpgradeable) {
agentSOs = agentSOs.filter((agent) =>
isAgentUpgradeable(savedObjectToAgent(agent), appContextService.getKibanaVersion())
);
total = agentSOs.length;
}
return {
agents: agentSOs.map(savedObjectToAgent),
total,
page,
perPage,
};
} catch (e) {
if (e.output?.payload?.message?.startsWith('The key is empty')) {
return {
agents: [],
total: 0,
page: 0,
perPage: 0,
};
} else {
throw e;
}
}
}
export async function listAllAgents(
soClient: SavedObjectsClientContract,
options: Omit<ListWithKuery, 'page' | 'perPage'> & {
showInactive: boolean;
}
): Promise<{
agents: Agent[];
total: number;
}> {
const { sortField = 'enrolled_at', sortOrder = 'desc', kuery, showInactive = false } = options;
const filters = [];
if (kuery && kuery !== '') {
filters.push(kuery);
}
if (showInactive === false) {
filters.push(ACTIVE_AGENT_CONDITION);
}
const { saved_objects: agentSOs, total } = await findAllSOs<AgentSOAttributes>(soClient, {
type: AGENT_SAVED_OBJECT_TYPE,
kuery: _joinFilters(filters),
sortField,
sortOrder,
});
return {
agents: agentSOs.map(savedObjectToAgent),
total,
};
}
export async function countInactiveAgents(
soClient: SavedObjectsClientContract,
options: Pick<ListWithKuery, 'kuery'>
): Promise<number> {
const { kuery } = options;
const filters = [INACTIVE_AGENT_CONDITION];
if (kuery && kuery !== '') {
filters.push(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery));
}
const { total } = await soClient.find<AgentSOAttributes>({
type: AGENT_SAVED_OBJECT_TYPE,
filter: _joinFilters(filters),
perPage: 0,
});
return total;
}
export async function getAgent(soClient: SavedObjectsClientContract, agentId: string) {
const agent = savedObjectToAgent(
await soClient.get<AgentSOAttributes>(AGENT_SAVED_OBJECT_TYPE, agentId)
);
return agent;
}
export async function getAgents(soClient: SavedObjectsClientContract, agentIds: string[]) {
const agentSOs = await soClient.bulkGet<AgentSOAttributes>(
agentIds.map((agentId) => ({
id: agentId,
type: AGENT_SAVED_OBJECT_TYPE,
}))
);
const agents = agentSOs.saved_objects.map(savedObjectToAgent);
return agents;
}
export async function getAgentByAccessAPIKeyId(
soClient: SavedObjectsClientContract,
accessAPIKeyId: string
): Promise<Agent> {
const response = await soClient.find<AgentSOAttributes>({
type: AGENT_SAVED_OBJECT_TYPE,
searchFields: ['access_api_key_id'],
search: escapeSearchQueryPhrase(accessAPIKeyId),
});
const [agent] = response.saved_objects.map(savedObjectToAgent);
if (!agent) {
throw Boom.notFound('Agent not found');
}
if (agent.access_api_key_id !== accessAPIKeyId) {
throw new Error('Agent api key id is not matching');
}
if (!agent.active) {
throw Boom.forbidden('Agent inactive');
}
return agent;
}
export async function updateAgent(
soClient: SavedObjectsClientContract,
agentId: string,
data: Partial<AgentSOAttributes>
) {
await soClient.update<AgentSOAttributes>(AGENT_SAVED_OBJECT_TYPE, agentId, data);
}
export async function bulkUpdateAgents(
soClient: SavedObjectsClientContract,
updateData: Array<{
agentId: string;
data: Partial<AgentSOAttributes>;
}>
) {
const updates: Array<SavedObjectsBulkUpdateObject<AgentSOAttributes>> = updateData.map(
({ agentId, data }) => ({
type: AGENT_SAVED_OBJECT_TYPE,
id: agentId,
attributes: data,
})
);
const res = await soClient.bulkUpdate<AgentSOAttributes>(updates);
return {
items: res.saved_objects.map((so) => ({
id: so.id,
success: !so.error,
error: so.error,
})),
};
}
export async function deleteAgent(soClient: SavedObjectsClientContract, agentId: string) {
await soClient.update<AgentSOAttributes>(AGENT_SAVED_OBJECT_TYPE, agentId, {
active: false,
});
}

View file

@ -11,7 +11,7 @@ import pMap from 'p-map';
import type { KueryNode } from '@kbn/es-query';
import { fromKueryExpression } from '@kbn/es-query';
import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { AGENTS_PREFIX } from '../../constants';
import type { AgentStatus } from '../../types';
import { AgentStatusKueryHelper } from '../../../common/services';
@ -70,8 +70,8 @@ export async function getAgentStatusForAgentPolicy(
...[
kuery,
filterKuery,
`${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`,
agentPolicyId ? `${AGENT_SAVED_OBJECT_TYPE}.policy_id:"${agentPolicyId}"` : undefined,
`${AGENTS_PREFIX}.attributes.active:true`,
agentPolicyId ? `${AGENTS_PREFIX}.policy_id:"${agentPolicyId}"` : undefined,
]
),
}),

View file

@ -7,7 +7,7 @@
import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server';
import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { AGENTS_PREFIX } from '../../constants';
import { getAgentsByKuery } from './crud';
import { unenrollAgent } from './unenroll';
@ -21,7 +21,7 @@ export async function unenrollForAgentPolicyId(
let page = 1;
while (hasMore) {
const { agents } = await getAgentsByKuery(esClient, {
kuery: `${AGENT_SAVED_OBJECT_TYPE}.policy_id:"${policyId}"`,
kuery: `${AGENTS_PREFIX}.policy_id:"${policyId}"`,
page: page++,
perPage: 1000,
showInactive: false,

View file

@ -7,8 +7,7 @@
import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server';
import type { Agent, AgentAction, AgentActionSOAttributes, BulkActionResult } from '../../types';
import { AGENT_ACTION_SAVED_OBJECT_TYPE } from '../../constants';
import type { Agent, BulkActionResult } from '../../types';
import { agentPolicyService } from '../../services';
import {
AgentReassignmentError,
@ -68,23 +67,6 @@ export async function sendUpgradeAgentAction({
});
}
export async function ackAgentUpgraded(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
agentAction: AgentAction
) {
const {
attributes: { ack_data: ackData },
} = await soClient.get<AgentActionSOAttributes>(AGENT_ACTION_SAVED_OBJECT_TYPE, agentAction.id);
if (!ackData) throw new Error('data missing from UPGRADE action');
const { version } = JSON.parse(ackData);
if (!version) throw new Error('version missing from UPGRADE action');
await updateAgent(esClient, agentAction.agent_id, {
upgraded_at: new Date().toISOString(),
upgrade_started_at: null,
});
}
export async function sendUpgradeAgentsActions(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,

View file

@ -1,72 +0,0 @@
/*
* 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 type { SavedObjectsClientContract, SavedObject } from 'src/core/server';
import type { EnrollmentAPIKey, EnrollmentAPIKeySOAttributes } from '../../types';
import { ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE } from '../../constants';
import { appContextService } from '../app_context';
import { normalizeKuery } from '../saved_object';
export async function listEnrollmentApiKeys(
soClient: SavedObjectsClientContract,
options: {
page?: number;
perPage?: number;
kuery?: string;
showInactive?: boolean;
}
): Promise<{ items: EnrollmentAPIKey[]; total: any; page: any; perPage: any }> {
const { page = 1, perPage = 20, kuery } = options;
// eslint-disable-next-line @typescript-eslint/naming-convention
const { saved_objects, total } = await soClient.find<EnrollmentAPIKeySOAttributes>({
type: ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
page,
perPage,
sortField: 'created_at',
sortOrder: 'desc',
filter:
kuery && kuery !== ''
? normalizeKuery(ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, kuery)
: undefined,
});
const items = saved_objects.map(savedObjectToEnrollmentApiKey);
return {
items,
total,
page,
perPage,
};
}
export async function getEnrollmentAPIKey(soClient: SavedObjectsClientContract, id: string) {
const so = await appContextService
.getEncryptedSavedObjects()
.getDecryptedAsInternalUser<EnrollmentAPIKeySOAttributes>(
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
id
);
return savedObjectToEnrollmentApiKey(so);
}
function savedObjectToEnrollmentApiKey({
error,
attributes,
id,
}: SavedObject<EnrollmentAPIKeySOAttributes>): EnrollmentAPIKey {
if (error) {
throw new Error(error.message);
}
return {
id,
...attributes,
};
}

View file

@ -6,23 +6,9 @@
*/
import type { ElasticsearchClient } from 'kibana/server';
import { first } from 'rxjs/operators';
import { appContextService } from '../app_context';
import { licenseService } from '../license';
import { FLEET_SERVER_SERVERS_INDEX } from '../../constants';
import { runFleetServerMigration } from './saved_object_migrations';
let _isFleetServerSetup = false;
let _isPending = false;
let _status: Promise<any> | undefined;
let _onResolve: (arg?: any) => void;
export function isFleetServerSetup() {
return _isFleetServerSetup;
}
/**
* Check if at least one fleet server is connected
*/
@ -35,48 +21,3 @@ export async function hasFleetServers(esClient: ElasticsearchClient) {
// @ts-expect-error value is number | TotalHits
return res.body.hits.total.value > 0;
}
export async function awaitIfFleetServerSetupPending() {
if (!_isPending) {
return;
}
return _status;
}
export async function startFleetServerSetup() {
_isPending = true;
_status = new Promise((resolve) => {
_onResolve = resolve;
});
const logger = appContextService.getLogger();
// Check for security
if (!appContextService.hasSecurity()) {
// Fleet will not work if security is not enabled
logger?.warn('Fleet requires the security plugin to be enabled.');
return;
}
// Log information about custom registry URL
const customUrl = appContextService.getConfig()?.registryUrl;
if (customUrl) {
logger.info(
`Custom registry url is an experimental feature and is unsupported. Using custom registry at ${customUrl}`
);
}
try {
// We need licence to be initialized before using the SO service.
await licenseService.getLicenseInformation$()?.pipe(first())?.toPromise();
await runFleetServerMigration();
_isFleetServerSetup = true;
} catch (err) {
logger?.error('Setup for central management of agents failed.');
logger?.error(err);
}
_isPending = false;
if (_onResolve) {
_onResolve();
}
}

View file

@ -1,201 +0,0 @@
/*
* 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 { isBoom } from '@hapi/boom';
import type { KibanaRequest } from 'src/core/server';
import {
ENROLLMENT_API_KEYS_INDEX,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
AGENT_POLICY_INDEX,
AGENTS_INDEX,
AGENT_SAVED_OBJECT_TYPE,
SO_SEARCH_LIMIT,
} from '../../../common';
import type {
FleetServerEnrollmentAPIKey,
AgentSOAttributes,
FleetServerAgent,
} from '../../../common';
import { listEnrollmentApiKeys, getEnrollmentAPIKey } from '../api_keys/enrollment_api_key_so';
import { appContextService } from '../app_context';
import { agentPolicyService } from '../agent_policy';
import { invalidateAPIKeys } from '../api_keys';
import { settingsService } from '..';
export async function runFleetServerMigration() {
await settingsService.settingsSetup(getInternalUserSOClient());
await Promise.all([migrateEnrollmentApiKeys(), migrateAgentPolicies(), migrateAgents()]);
}
function getInternalUserSOClient() {
const fakeRequest = {
headers: {},
getBasePath: () => '',
path: '/',
route: { settings: {} },
url: {
href: '/',
},
raw: {
req: {
url: '/',
},
},
} as unknown as KibanaRequest;
return appContextService.getInternalUserSOClient(fakeRequest);
}
async function migrateAgents() {
const esClient = appContextService.getInternalUserESClient();
const soClient = getInternalUserSOClient();
const logger = appContextService.getLogger();
let hasMore = true;
let hasAgents = false;
while (hasMore) {
const res = await soClient.find({
type: AGENT_SAVED_OBJECT_TYPE,
page: 1,
perPage: 100,
});
if (res.total === 0) {
hasMore = false;
} else {
hasAgents = true;
}
for (const so of res.saved_objects) {
try {
const { attributes } = await appContextService
.getEncryptedSavedObjects()
.getDecryptedAsInternalUser<AgentSOAttributes>(AGENT_SAVED_OBJECT_TYPE, so.id);
await invalidateAPIKeys(
[attributes.access_api_key_id, attributes.default_api_key_id].filter(
(keyId): keyId is string => keyId !== undefined
)
).catch((error) => {
logger.error(`Invalidating API keys for agent ${so.id} failed: ${error.message}`);
});
const body: FleetServerAgent = {
type: attributes.type,
active: false,
enrolled_at: attributes.enrolled_at,
unenrolled_at: new Date().toISOString(),
unenrollment_started_at: attributes.unenrollment_started_at,
upgraded_at: attributes.upgraded_at,
upgrade_started_at: attributes.upgrade_started_at,
access_api_key_id: attributes.access_api_key_id,
user_provided_metadata: attributes.user_provided_metadata,
local_metadata: attributes.local_metadata,
policy_id: attributes.policy_id,
policy_revision_idx: attributes.policy_revision || undefined,
last_checkin: attributes.last_checkin,
last_checkin_status: attributes.last_checkin_status,
default_api_key_id: attributes.default_api_key_id,
default_api_key: attributes.default_api_key,
packages: attributes.packages,
};
await esClient.create({
index: AGENTS_INDEX,
body,
id: so.id,
refresh: 'wait_for',
});
await soClient.delete(AGENT_SAVED_OBJECT_TYPE, so.id);
} catch (error) {
// swallow 404 error has multiple Kibana can run the migration at the same time
if (!is404Error(error)) {
throw error;
}
}
}
}
// Update settings to show migration modal
if (hasAgents) {
await settingsService.saveSettings(soClient, {
has_seen_fleet_migration_notice: false,
});
}
}
async function migrateEnrollmentApiKeys() {
const esClient = appContextService.getInternalUserESClient();
const soClient = getInternalUserSOClient();
let hasMore = true;
while (hasMore) {
const res = await listEnrollmentApiKeys(soClient, {
page: 1,
perPage: 100,
});
if (res.total === 0) {
hasMore = false;
}
for (const item of res.items) {
try {
const key = await getEnrollmentAPIKey(soClient, item.id);
const body: FleetServerEnrollmentAPIKey = {
api_key: key.api_key,
api_key_id: key.api_key_id,
active: key.active,
created_at: key.created_at,
name: key.name,
policy_id: key.policy_id,
};
await esClient.create({
index: ENROLLMENT_API_KEYS_INDEX,
body,
id: key.id,
refresh: 'wait_for',
});
await soClient.delete(ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, key.id);
} catch (error) {
// swallow 404 error has multiple Kibana can run the migration at the same time
if (!is404Error(error)) {
throw error;
}
}
}
}
}
async function migrateAgentPolicies() {
const esClient = appContextService.getInternalUserESClient();
const soClient = getInternalUserSOClient();
const { items: agentPolicies } = await agentPolicyService.list(soClient, {
perPage: SO_SEARCH_LIMIT,
});
await Promise.all(
agentPolicies.map(async (agentPolicy) => {
const res = await esClient.search({
index: AGENT_POLICY_INDEX,
q: `policy_id:${agentPolicy.id}`,
track_total_hits: true,
ignore_unavailable: true,
});
// @ts-expect-error value is number | TotalHits
if (res.body.hits.total.value === 0) {
return agentPolicyService.createFleetServerPolicy(soClient, agentPolicy.id);
}
})
);
}
function is404Error(error: any) {
return isBoom(error) && error.output.statusCode === 404;
}

View file

@ -26,7 +26,6 @@ import { generateEnrollmentAPIKey, hasEnrollementAPIKeysForPolicy } from './api_
import { settingsService } from '.';
import { awaitIfPending } from './setup_utils';
import { ensureFleetServerAgentPoliciesExists } from './agents';
import { awaitIfFleetServerSetupPending } from './fleet_server';
import { ensureFleetFinalPipelineIsInstalled } from './epm/elasticsearch/ingest_pipeline/install';
import { ensureDefaultComponentTemplate } from './epm/elasticsearch/template/install';
import { getInstallations, installPackage } from './epm/packages';
@ -68,7 +67,6 @@ async function createSetupSideEffects(
const defaultOutput = await outputService.ensureDefaultOutput(soClient);
await awaitIfFleetServerSetupPending();
if (appContextService.getConfig()?.agentIdVerificationEnabled) {
await ensureFleetGlobalEsAssets(soClient, esClient);
}

View file

@ -13,7 +13,6 @@ export type {
AgentType,
AgentAction,
AgentPolicyAction,
AgentPolicyActionV7_9,
BaseAgentActionSOAttributes,
AgentActionSOAttributes,
AgentPolicyActionSOAttributes,

View file

@ -9,7 +9,7 @@ import { map } from 'lodash';
import { i18n } from '@kbn/i18n';
import { useQuery } from 'react-query';
import { AGENT_SAVED_OBJECT_TYPE, Agent } from '../../../fleet/common';
import { AGENTS_PREFIX, Agent } from '../../../fleet/common';
import { useErrorToast } from '../common/hooks/use_error_toast';
import { useKibana } from '../common/lib/kibana';
@ -30,7 +30,7 @@ export const useAgentPolicyAgentIds = ({
return useQuery<{ agents: Agent[] }, unknown, string[]>(
['agentPolicyAgentIds', agentPolicyId],
() => {
const kuery = `${AGENT_SAVED_OBJECT_TYPE}.policy_id:${agentPolicyId}`;
const kuery = `${AGENTS_PREFIX}.policy_id:${agentPolicyId}`;
return http.get(`/internal/osquery/fleet_wrapper/agents`, {
query: {