Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fleet] Use fleet server indices for enrollment keys and to list agents with a feature flag #86179

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4a8791b
[Fleet] Use fleet server indices for enrollment keys
nchaulet Dec 16, 2020
e704999
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 22, 2020
272926f
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 22, 2020
4b93480
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 27, 2020
87c3452
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 28, 2020
cae8106
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 29, 2020
f738b37
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 29, 2020
47be337
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 29, 2020
d75033e
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Dec 30, 2020
5f04a27
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Jan 3, 2021
175a379
[Fleet Server] Add support for index based agents
patrykkopycinski Jan 3, 2021
0989147
add missing files
patrykkopycinski Jan 3, 2021
1fa3c49
fix types
patrykkopycinski Jan 3, 2021
4f34ef5
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
patrykkopycinski Jan 6, 2021
d9e3292
Fix after review
nchaulet Jan 10, 2021
e64915b
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
nchaulet Jan 10, 2021
2f7c48c
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
nchaulet Jan 11, 2021
af829e8
fix after review
nchaulet Jan 11, 2021
670a8f4
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
nchaulet Jan 18, 2021
60eab63
add support for agent policy in fleet server
nchaulet Jan 18, 2021
4647e84
Fix type issue
nchaulet Jan 18, 2021
b888fe2
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
nchaulet Jan 18, 2021
fe8902f
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
nchaulet Jan 19, 2021
cbafae0
Add forgeted file for migrations
nchaulet Jan 19, 2021
74e89bc
Merge branch 'master' of github.com:elastic/kibana into feature-poc-k…
nchaulet Jan 20, 2021
18293e9
fix after review
nchaulet Jan 20, 2021
533e506
Merge branch 'master' into feature-poc-kibana-fleet-server-feature-flag
kibanamachine Jan 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/common/constants/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export const AGENT_UPDATE_ACTIONS_INTERVAL_MS = 5000;

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';
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/common/constants/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { defaultPackages } from './epm';
import { AgentPolicy } from '../types';
export const AGENT_POLICY_SAVED_OBJECT_TYPE = 'ingest-agent-policies';

export const AGENT_POLICY_INDEX = '.fleet-policies';
export const agentPolicyStatuses = {
Active: 'active',
Inactive: 'inactive',
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/common/constants/enrollment_api_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
*/

export const ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE = 'fleet-enrollment-api-keys';

export const ENROLLMENT_API_KEYS_INDEX = '.fleet-enrollment-api-keys';
4 changes: 2 additions & 2 deletions x-pack/plugins/fleet/common/services/agent_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function getAgentStatus(agent: Agent, now: number = Date.now()): AgentSta
}

export function buildKueryForEnrollingAgents() {
return `not ${AGENT_SAVED_OBJECT_TYPE}.last_checkin:*`;
return `not (${AGENT_SAVED_OBJECT_TYPE}.last_checkin:*)`;
}

export function buildKueryForUnenrollingAgents() {
Expand All @@ -53,7 +53,7 @@ export function buildKueryForOnlineAgents() {
}

export function buildKueryForErrorAgents() {
return `( ${AGENT_SAVED_OBJECT_TYPE}.last_checkin_status:error or ${AGENT_SAVED_OBJECT_TYPE}.last_checkin_status:degraded )`;
return `${AGENT_SAVED_OBJECT_TYPE}.last_checkin_status:error or ${AGENT_SAVED_OBJECT_TYPE}.last_checkin_status:degraded`;
}

export function buildKueryForOfflineAgents() {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface FleetConfigType {
registryUrl?: string;
registryProxyUrl?: string;
agents: {
fleetServerEnabled: boolean;
enabled: boolean;
tlsCheckDisabled: boolean;
pollingRequestTimeout: number;
Expand Down
34 changes: 34 additions & 0 deletions x-pack/plugins/fleet/common/types/models/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,37 @@ export interface FullAgentPolicyKibanaConfig {
protocol: string;
path?: string;
}

// Generated from Fleet Server schema.json

/**
* A policy that an Elastic Agent is attached to
*/
export interface FleetServerPolicy {
/**
* Date/time the policy revision was created
*/
'@timestamp'?: string;
/**
* The ID of the policy
*/
policy_id: string;
/**
* The revision index of the policy
*/
revision_idx: number;
/**
* The coordinator index of the policy
*/
coordinator_idx: number;
/**
* The opaque payload.
*/
data: {
[k: string]: unknown;
};
/**
* True when this policy is the default policy to start Fleet Server
*/
default_fleet_server: boolean;
}
28 changes: 28 additions & 0 deletions x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,31 @@ export interface EnrollmentAPIKey {
}

export type EnrollmentAPIKeySOAttributes = Omit<EnrollmentAPIKey, 'id'>;

// Generated

/**
* An Elastic Agent enrollment API key
*/
export interface FleetServerEnrollmentAPIKey {
/**
* True when the key is active
*/
active?: boolean;
/**
* The unique identifier for the enrollment key, currently xid
*/
api_key_id: string;
/**
* Api key
*/
api_key: string;
/**
* Enrollment key name
*/
name?: string;
policy_id?: string;
expire_at?: string;
created_at?: string;
updated_at?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const createConfigurationMock = (): FleetConfigType => {
registryProxyUrl: '',
agents: {
enabled: true,
fleetServerEnabled: false,
tlsCheckDisabled: true,
pollingRequestTimeout: 1000,
maxConcurrentConnections: 100,
Expand Down
12 changes: 8 additions & 4 deletions x-pack/plugins/fleet/server/collectors/agent_collectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { SavedObjectsClient } from 'kibana/server';
import { ElasticsearchClient, SavedObjectsClient } from 'kibana/server';
import * as AgentService from '../services/agents';
export interface AgentUsage {
total: number;
Expand All @@ -13,9 +13,12 @@ export interface AgentUsage {
offline: number;
}

export const getAgentUsage = async (soClient?: SavedObjectsClient): Promise<AgentUsage> => {
export const getAgentUsage = async (
soClient?: SavedObjectsClient,
esClient?: ElasticsearchClient
): Promise<AgentUsage> => {
// TODO: unsure if this case is possible at all.
if (!soClient) {
if (!soClient || !esClient) {
return {
total: 0,
online: 0,
Expand All @@ -24,7 +27,8 @@ export const getAgentUsage = async (soClient?: SavedObjectsClient): Promise<Agen
};
}
const { total, online, error, offline } = await AgentService.getAgentStatusForAgentPolicy(
soClient
soClient,
esClient
);
return {
total,
Expand Down
9 changes: 6 additions & 3 deletions x-pack/plugins/fleet/server/collectors/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
*/

import { CoreSetup } from 'kibana/server';
import { SavedObjectsClient } from '../../../../../src/core/server';
import { ElasticsearchClient, SavedObjectsClient } from '../../../../../src/core/server';

export async function getInternalSavedObjectsClient(core: CoreSetup) {
export async function getInternalClients(
core: CoreSetup
): Promise<[SavedObjectsClient, ElasticsearchClient]> {
return core.getStartServices().then(async ([coreStart]) => {
const savedObjectsRepo = coreStart.savedObjects.createInternalRepository();
return new SavedObjectsClient(savedObjectsRepo);
const esClient = coreStart.elasticsearch.client.asInternalUser;
return [new SavedObjectsClient(savedObjectsRepo), esClient];
});
}
6 changes: 3 additions & 3 deletions x-pack/plugins/fleet/server/collectors/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { CoreSetup } from 'kibana/server';
import { getIsAgentsEnabled } from './config_collectors';
import { AgentUsage, getAgentUsage } from './agent_collectors';
import { getInternalSavedObjectsClient } from './helpers';
import { getInternalClients } from './helpers';
import { PackageUsage, getPackageUsage } from './package_collectors';
import { FleetConfigType } from '..';

Expand All @@ -34,10 +34,10 @@ export function registerFleetUsageCollector(
type: 'fleet',
isReady: () => true,
fetch: async () => {
const soClient = await getInternalSavedObjectsClient(core);
const [soClient, esClient] = await getInternalClients(core);
return {
agents_enabled: getIsAgentsEnabled(config),
agents: await getAgentUsage(soClient),
agents: await getAgentUsage(soClient, esClient),
packages: await getPackageUsage(soClient),
};
},
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/fleet/server/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ export {
// Defaults
DEFAULT_AGENT_POLICY,
DEFAULT_OUTPUT,
// Fleet Server index
ENROLLMENT_API_KEYS_INDEX,
AGENTS_INDEX,
} from '../../common';
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const config: PluginConfigDescriptor = {
registryProxyUrl: schema.maybe(schema.uri({ scheme: ['http', 'https'] })),
agents: schema.object({
enabled: schema.boolean({ defaultValue: true }),
fleetServerEnabled: schema.boolean({ defaultValue: false }),
tlsCheckDisabled: schema.boolean({ defaultValue: false }),
pollingRequestTimeout: schema.number({
defaultValue: AGENT_POLLING_REQUEST_TIMEOUT_MS,
Expand Down
7 changes: 6 additions & 1 deletion x-pack/plugins/fleet/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { loggingSystemMock, savedObjectsServiceMock } from 'src/core/server/mocks';
import {
elasticsearchServiceMock,
loggingSystemMock,
savedObjectsServiceMock,
} from 'src/core/server/mocks';
import { FleetAppContext } from './plugin';
import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks';
import { securityMock } from '../../security/server/mocks';
Expand All @@ -13,6 +17,7 @@ import { AgentPolicyServiceInterface, AgentService } from './services';

export const createAppContextStartContractMock = (): FleetAppContext => {
return {
elasticsearch: elasticsearchServiceMock.createStart(),
encryptedSavedObjectsStart: encryptedSavedObjectsMock.createStart(),
savedObjects: savedObjectsServiceMock.createStartContract(),
security: securityMock.createStart(),
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/fleet/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { first } from 'rxjs/operators';
import {
CoreSetup,
CoreStart,
ElasticsearchServiceStart,
Logger,
Plugin,
PluginInitializerContext,
Expand Down Expand Up @@ -80,6 +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';

export interface FleetSetupDeps {
licensing: LicensingPluginSetup;
Expand All @@ -96,6 +98,7 @@ export interface FleetStartDeps {
}

export interface FleetAppContext {
elasticsearch: ElasticsearchServiceStart;
encryptedSavedObjectsStart?: EncryptedSavedObjectsPluginStart;
encryptedSavedObjectsSetup?: EncryptedSavedObjectsPluginSetup;
security?: SecurityPluginStart;
Expand Down Expand Up @@ -276,6 +279,7 @@ export class FleetPlugin

public async start(core: CoreStart, plugins: FleetStartDeps): Promise<FleetStartContract> {
await appContextService.start({
elasticsearch: core.elasticsearch,
encryptedSavedObjectsStart: plugins.encryptedSavedObjects,
encryptedSavedObjectsSetup: this.encryptedSavedObjectsSetup,
security: plugins.security,
Expand All @@ -291,6 +295,13 @@ export class FleetPlugin
licenseService.start(this.licensing$);
agentCheckinState.start();

const fleetServerEnabled = appContextService.getConfig()?.agents?.fleetServerEnabled;
if (fleetServerEnabled) {
// We need licence to be initialized before using the SO service.
await this.licensing$.pipe(first()).toPromise();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we wait for licensing before starting migration?

Copy link
Member Author

@nchaulet nchaulet Jan 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need licensing to be available so the SO client is correctly initialized. it probably need a comment here

await runFleetServerMigration();
}

return {
esIndexPatternService: new ESIndexPatternSavedObjectService(),
packageService: {
Expand Down
10 changes: 9 additions & 1 deletion x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@

import { postAgentAcksHandlerBuilder } from './acks_handlers';
import {
ElasticsearchClient,
KibanaResponseFactory,
RequestHandlerContext,
SavedObjectsClientContract,
} from 'kibana/server';
import { httpServerMock, savedObjectsClientMock } from '../../../../../../src/core/server/mocks';
import {
elasticsearchServiceMock,
httpServerMock,
savedObjectsClientMock,
} from '../../../../../../src/core/server/mocks';
import { PostAgentAcksResponse } from '../../../common/types/rest_spec';
import { AckEventSchema } from '../../types/models';
import { AcksService } from '../../services/agents';
Expand Down Expand Up @@ -45,9 +50,11 @@ describe('test acks schema', () => {
describe('test acks handlers', () => {
let mockResponse: jest.Mocked<KibanaResponseFactory>;
let mockSavedObjectsClient: jest.Mocked<SavedObjectsClientContract>;
let mockElasticsearchClient: jest.Mocked<ElasticsearchClient>;

beforeEach(() => {
mockSavedObjectsClient = savedObjectsClientMock.create();
mockElasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
mockResponse = httpServerMock.createResponseFactory();
});

Expand Down Expand Up @@ -81,6 +88,7 @@ describe('test acks handlers', () => {
id: 'agent',
}),
getSavedObjectsClientContract: jest.fn().mockReturnValueOnce(mockSavedObjectsClient),
getElasticsearchClientContract: jest.fn().mockReturnValueOnce(mockElasticsearchClient),
saveAgentEvents: jest.fn(),
} as jest.Mocked<AcksService>;

Expand Down
8 changes: 7 additions & 1 deletion x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const postAgentAcksHandlerBuilder = function (
return async (context, request, response) => {
try {
const soClient = ackService.getSavedObjectsClientContract(request);
const esClient = ackService.getElasticsearchClientContract();
const agent = await ackService.authenticateAgentWithAccessToken(soClient, request);
const agentEvents = request.body.events as AgentEvent[];

Expand All @@ -33,7 +34,12 @@ export const postAgentAcksHandlerBuilder = function (
});
}

const agentActions = await ackService.acknowledgeAgentActions(soClient, agent, agentEvents);
const agentActions = await ackService.acknowledgeAgentActions(
soClient,
esClient,
agent,
agentEvents
);

if (agentActions.length > 0) {
await ackService.saveAgentEvents(soClient, agentEvents);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@

import { NewAgentActionSchema } from '../../types/models';
import {
ElasticsearchClient,
KibanaResponseFactory,
RequestHandlerContext,
SavedObjectsClientContract,
} from 'kibana/server';
import { savedObjectsClientMock, httpServerMock } from 'src/core/server/mocks';
import {
elasticsearchServiceMock,
savedObjectsClientMock,
httpServerMock,
} from 'src/core/server/mocks';
import { ActionsService } from '../../services/agents';
import { AgentAction } from '../../../common/types/models';
import { postNewAgentActionHandlerBuilder } from './actions_handlers';
Expand Down Expand Up @@ -41,9 +46,11 @@ describe('test actions handlers schema', () => {
describe('test actions handlers', () => {
let mockResponse: jest.Mocked<KibanaResponseFactory>;
let mockSavedObjectsClient: jest.Mocked<SavedObjectsClientContract>;
let mockElasticsearchClient: jest.Mocked<ElasticsearchClient>;

beforeEach(() => {
mockSavedObjectsClient = savedObjectsClientMock.create();
mockElasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
mockResponse = httpServerMock.createResponseFactory();
});

Expand Down Expand Up @@ -84,6 +91,11 @@ describe('test actions handlers', () => {
savedObjects: {
client: mockSavedObjectsClient,
},
elasticsearch: {
client: {
asInternalUser: mockElasticsearchClient,
},
},
},
} as unknown) as RequestHandlerContext,
mockRequest,
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ export const postNewAgentActionHandlerBuilder = function (
return async (context, request, response) => {
try {
const soClient = context.core.savedObjects.client;
const esClient = context.core.elasticsearch.client.asInternalUser;

const agent = await actionsService.getAgent(soClient, request.params.agentId);
const agent = await actionsService.getAgent(soClient, esClient, request.params.agentId);

const newAgentAction = request.body.action;

Expand Down
Loading