[Fleet] Install the Fleet Server package during setup (#89224)

This commit is contained in:
Nicolas Chaulet 2021-01-29 08:41:36 -05:00 committed by GitHub
parent 049135192e
commit da1a4e947a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 6 deletions

View file

@ -24,3 +24,4 @@ export const AGENT_POLICY_ROLLOUT_RATE_LIMIT_INTERVAL_MS = 1000;
export const AGENT_POLICY_ROLLOUT_RATE_LIMIT_REQUEST_PER_INTERVAL = 5;
export const AGENTS_INDEX = '.fleet-agents';
export const AGENT_ACTIONS_INDEX = '.fleet-actions';

View file

@ -8,6 +8,8 @@ export const ASSETS_SAVED_OBJECT_TYPE = 'epm-packages-assets';
export const INDEX_PATTERN_SAVED_OBJECT_TYPE = 'index-pattern';
export const MAX_TIME_COMPLETE_INSTALL = 60000;
export const FLEET_SERVER_PACKAGE = 'fleet_server';
export const requiredPackages = {
System: 'system',
Endpoint: 'endpoint',

View file

@ -19,3 +19,12 @@ export * from './settings';
// for the actual setting to differ from the default. Can we retrieve the real
// setting in the future?
export const SO_SEARCH_LIMIT = 10000;
export const FLEET_SERVER_INDICES = [
'.fleet-actions',
'.fleet-agents',
'.fleet-enrollment-api-keys',
'.fleet-policies',
'.fleet-policies-leader',
'.fleet-servers',
];

View file

@ -6,6 +6,7 @@
import { ElasticsearchClient, SavedObjectsClient } from 'kibana/server';
import * as AgentService from '../services/agents';
import { isFleetServerSetup } from '../services/fleet_server_migration';
export interface AgentUsage {
total: number;
online: number;
@ -18,7 +19,7 @@ export const getAgentUsage = async (
esClient?: ElasticsearchClient
): Promise<AgentUsage> => {
// TODO: unsure if this case is possible at all.
if (!soClient || !esClient) {
if (!soClient || !esClient || !(await isFleetServerSetup())) {
return {
total: 0,
online: 0,
@ -26,6 +27,7 @@ export const getAgentUsage = async (
offline: 0,
};
}
const { total, online, error, offline } = await AgentService.getAgentStatusForAgentPolicy(
soClient,
esClient

View file

@ -81,7 +81,7 @@ import { agentCheckinState } from './services/agents/checkin/state';
import { registerFleetUsageCollector } from './collectors/register';
import { getInstallation } from './services/epm/packages';
import { makeRouterEnforcingSuperuser } from './routes/security';
import { runFleetServerMigration } from './services/fleet_server_migration';
import { isFleetServerSetup } from './services/fleet_server_migration';
export interface FleetSetupDeps {
licensing: LicensingPluginSetup;
@ -299,7 +299,14 @@ export class FleetPlugin
if (fleetServerEnabled) {
// We need licence to be initialized before using the SO service.
await this.licensing$.pipe(first()).toPromise();
await runFleetServerMigration();
const fleetSetup = await isFleetServerSetup();
if (!fleetSetup) {
this.logger?.warn(
'Extra setup is needed to be able to use central management for agent, please visit the Fleet app in Kibana.'
);
}
}
return {

View file

@ -9,15 +9,39 @@ import {
ENROLLMENT_API_KEYS_INDEX,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
FleetServerEnrollmentAPIKey,
FLEET_SERVER_PACKAGE,
FLEET_SERVER_INDICES,
} from '../../common';
import { listEnrollmentApiKeys, getEnrollmentAPIKey } from './api_keys/enrollment_api_key_so';
import { appContextService } from './app_context';
import { getInstallation } from './epm/packages';
export async function isFleetServerSetup() {
const pkgInstall = await getInstallation({
savedObjectsClient: getInternalUserSOClient(),
pkgName: FLEET_SERVER_PACKAGE,
});
if (!pkgInstall) {
return false;
}
const esClient = appContextService.getInternalUserESClient();
const exists = await Promise.all(
FLEET_SERVER_INDICES.map(async (index) => {
const res = await esClient.indices.exists({
index,
});
return res.statusCode !== 404;
})
);
return exists.every((exist) => exist === true);
}
export async function runFleetServerMigration() {
const logger = appContextService.getLogger();
logger.info('Starting fleet server migration');
await migrateEnrollmentApiKeys();
logger.info('Fleet server migration finished');
}
function getInternalUserSOClient() {

View file

@ -11,6 +11,7 @@ import { agentPolicyService } from './agent_policy';
import { outputService } from './output';
import {
ensureInstalledDefaultPackages,
ensureInstalledPackage,
ensurePackagesCompletedInstall,
} from './epm/packages/install';
import {
@ -20,6 +21,8 @@ import {
Installation,
Output,
DEFAULT_AGENT_POLICIES_PACKAGES,
FLEET_SERVER_PACKAGE,
FLEET_SERVER_INDICES,
} from '../../common';
import { SO_SEARCH_LIMIT } from '../constants';
import { getPackageInfo } from './epm/packages';
@ -29,6 +32,8 @@ import { settingsService } from '.';
import { awaitIfPending } from './setup_utils';
import { createDefaultSettings } from './settings';
import { ensureAgentActionPolicyChangeExists } from './agents';
import { appContextService } from './app_context';
import { runFleetServerMigration } from './fleet_server_migration';
const FLEET_ENROLL_USERNAME = 'fleet_enroll';
const FLEET_ENROLL_ROLE = 'fleet_enroll';
@ -77,6 +82,15 @@ async function createSetupSideEffects(
// By moving this outside of the Promise.all, the upgrade will occur first, and then we'll attempt to reinstall any
// packages that are stuck in the installing state.
await ensurePackagesCompletedInstall(soClient, callCluster);
if (appContextService.getConfig()?.agents.fleetServerEnabled) {
await ensureInstalledPackage({
savedObjectsClient: soClient,
pkgName: FLEET_SERVER_PACKAGE,
callCluster,
});
await ensureFleetServerIndicesCreated(esClient);
await runFleetServerMigration();
}
// If we just created the default policy, ensure default packages are added to it
if (defaultAgentPolicyCreated) {
@ -144,6 +158,21 @@ async function updateFleetRoleIfExists(callCluster: CallESAsCurrentUser) {
return putFleetRole(callCluster);
}
async function ensureFleetServerIndicesCreated(esClient: ElasticsearchClient) {
await Promise.all(
FLEET_SERVER_INDICES.map(async (index) => {
const res = await esClient.indices.exists({
index,
});
if (res.statusCode === 404) {
await esClient.indices.create({
index,
});
}
})
);
}
async function putFleetRole(callCluster: CallESAsCurrentUser) {
return callCluster('transport.request', {
method: 'PUT',