Skip to content

Commit 85bb65b

Browse files
authored
[Security Solution] Give notice when endpoint policy is out of date (#83469) (#83979)
1 parent 4652dee commit 85bb65b

File tree

24 files changed

+715
-219
lines changed

24 files changed

+715
-219
lines changed

x-pack/plugins/fleet/server/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ import {
1313
} from '../common';
1414

1515
export { default as apm } from 'elastic-apm-node';
16-
export { AgentService, ESIndexPatternService, getRegistryUrl, PackageService } from './services';
16+
export {
17+
AgentService,
18+
ESIndexPatternService,
19+
getRegistryUrl,
20+
PackageService,
21+
AgentPolicyServiceInterface,
22+
} from './services';
1723
export { FleetSetupContract, FleetSetupDeps, FleetStartContract, ExternalCallback } from './plugin';
1824

1925
export const config: PluginConfigDescriptor = {

x-pack/plugins/fleet/server/mocks.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { FleetAppContext } from './plugin';
99
import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks';
1010
import { securityMock } from '../../security/server/mocks';
1111
import { PackagePolicyServiceInterface } from './services/package_policy';
12+
import { AgentPolicyServiceInterface, AgentService } from './services';
1213

1314
export const createAppContextStartContractMock = (): FleetAppContext => {
1415
return {
@@ -35,3 +36,28 @@ export const createPackagePolicyServiceMock = () => {
3536
update: jest.fn(),
3637
} as jest.Mocked<PackagePolicyServiceInterface>;
3738
};
39+
40+
/**
41+
* Create mock AgentPolicyService
42+
*/
43+
44+
export const createMockAgentPolicyService = (): jest.Mocked<AgentPolicyServiceInterface> => {
45+
return {
46+
get: jest.fn(),
47+
list: jest.fn(),
48+
getDefaultAgentPolicyId: jest.fn(),
49+
getFullAgentPolicy: jest.fn(),
50+
};
51+
};
52+
53+
/**
54+
* Creates a mock AgentService
55+
*/
56+
export const createMockAgentService = (): jest.Mocked<AgentService> => {
57+
return {
58+
getAgentStatusById: jest.fn(),
59+
authenticateAgentWithAccessToken: jest.fn(),
60+
getAgent: jest.fn(),
61+
listAgents: jest.fn(),
62+
};
63+
};

x-pack/plugins/fleet/server/plugin.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ import {
5858
ESIndexPatternSavedObjectService,
5959
ESIndexPatternService,
6060
AgentService,
61+
AgentPolicyServiceInterface,
62+
agentPolicyService,
6163
packagePolicyService,
6264
PackageService,
6365
} from './services';
@@ -134,6 +136,7 @@ export interface FleetStartContract {
134136
* Services for Fleet's package policies
135137
*/
136138
packagePolicyService: typeof packagePolicyService;
139+
agentPolicyService: AgentPolicyServiceInterface;
137140
/**
138141
* Register callbacks for inclusion in fleet API processing
139142
* @param args
@@ -292,6 +295,12 @@ export class FleetPlugin
292295
getAgentStatusById,
293296
authenticateAgentWithAccessToken,
294297
},
298+
agentPolicyService: {
299+
get: agentPolicyService.get,
300+
list: agentPolicyService.list,
301+
getDefaultAgentPolicyId: agentPolicyService.getDefaultAgentPolicyId,
302+
getFullAgentPolicy: agentPolicyService.getFullAgentPolicy,
303+
},
295304
packagePolicyService,
296305
registerExternalCallback: (...args: ExternalCallback) => {
297306
return appContextService.addExternalCallback(...args);

x-pack/plugins/fleet/server/services/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import * as settingsService from './settings';
1010
import { getAgent, listAgents } from './agents';
1111

1212
export { ESIndexPatternSavedObjectService } from './es_index_pattern';
13+
import { agentPolicyService } from './agent_policy';
1314

1415
export { getRegistryUrl } from './epm/registry/registry_url';
1516

@@ -60,6 +61,13 @@ export interface AgentService {
6061
listAgents: typeof listAgents;
6162
}
6263

64+
export interface AgentPolicyServiceInterface {
65+
get: typeof agentPolicyService['get'];
66+
list: typeof agentPolicyService['list'];
67+
getDefaultAgentPolicyId: typeof agentPolicyService['getDefaultAgentPolicyId'];
68+
getFullAgentPolicy: typeof agentPolicyService['getFullAgentPolicy'];
69+
}
70+
6371
// Saved object services
6472
export { agentPolicyService } from './agent_policy';
6573
export { packagePolicyService } from './package_policy';

x-pack/plugins/security_solution/common/endpoint/generate_data.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,29 @@ const APPLIED_POLICIES: Array<{
118118
name: string;
119119
id: string;
120120
status: HostPolicyResponseActionStatus;
121+
endpoint_policy_version: number;
122+
version: number;
121123
}> = [
122124
{
123125
name: 'Default',
124126
id: '00000000-0000-0000-0000-000000000000',
125127
status: HostPolicyResponseActionStatus.success,
128+
endpoint_policy_version: 1,
129+
version: 3,
126130
},
127131
{
128132
name: 'With Eventing',
129133
id: 'C2A9093E-E289-4C0A-AA44-8C32A414FA7A',
130134
status: HostPolicyResponseActionStatus.success,
135+
endpoint_policy_version: 3,
136+
version: 5,
131137
},
132138
{
133139
name: 'Detect Malware Only',
134140
id: '47d7965d-6869-478b-bd9c-fb0d2bb3959f',
135141
status: HostPolicyResponseActionStatus.success,
142+
endpoint_policy_version: 4,
143+
version: 9,
136144
},
137145
];
138146

@@ -251,6 +259,8 @@ interface HostInfo {
251259
id: string;
252260
status: HostPolicyResponseActionStatus;
253261
name: string;
262+
endpoint_policy_version: number;
263+
version: number;
254264
};
255265
};
256266
};
@@ -1332,7 +1342,7 @@ export class EndpointDocGenerator {
13321342
allStatus?: HostPolicyResponseActionStatus;
13331343
policyDataStream?: DataStream;
13341344
} = {}): HostPolicyResponse {
1335-
const policyVersion = this.seededUUIDv4();
1345+
const policyVersion = this.randomN(10);
13361346
const status = () => {
13371347
return allStatus || this.randomHostPolicyResponseActionStatus();
13381348
};
@@ -1501,6 +1511,8 @@ export class EndpointDocGenerator {
15011511
status: this.commonInfo.Endpoint.policy.applied.status,
15021512
version: policyVersion,
15031513
name: this.commonInfo.Endpoint.policy.applied.name,
1514+
endpoint_policy_version: this.commonInfo.Endpoint.policy.applied
1515+
.endpoint_policy_version,
15041516
},
15051517
},
15061518
},

x-pack/plugins/security_solution/common/endpoint/types/index.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ export interface HostResultList {
299299
request_page_index: number;
300300
/* the version of the query strategy */
301301
query_strategy_version: MetadataQueryStrategyVersions;
302+
/* policy IDs and versions */
303+
policy_info?: HostInfo['policy_info'];
302304
}
303305

304306
/**
@@ -520,9 +522,30 @@ export enum MetadataQueryStrategyVersions {
520522
VERSION_2 = 'v2',
521523
}
522524

525+
export type PolicyInfo = Immutable<{
526+
revision: number;
527+
id: string;
528+
}>;
529+
523530
export type HostInfo = Immutable<{
524531
metadata: HostMetadata;
525532
host_status: HostStatus;
533+
policy_info?: {
534+
agent: {
535+
/**
536+
* As set in Kibana
537+
*/
538+
configured: PolicyInfo;
539+
/**
540+
* Last reported running in agent (may lag behind configured)
541+
*/
542+
applied: PolicyInfo;
543+
};
544+
/**
545+
* Current intended 'endpoint' package policy
546+
*/
547+
endpoint: PolicyInfo;
548+
};
526549
/* the version of the query strategy */
527550
query_strategy_version: MetadataQueryStrategyVersions;
528551
}>;
@@ -558,6 +581,8 @@ export type HostMetadata = Immutable<{
558581
id: string;
559582
status: HostPolicyResponseActionStatus;
560583
name: string;
584+
endpoint_policy_version: number;
585+
version: number;
561586
};
562587
};
563588
};
@@ -1068,7 +1093,8 @@ export interface HostPolicyResponse {
10681093
Endpoint: {
10691094
policy: {
10701095
applied: {
1071-
version: string;
1096+
version: number;
1097+
endpoint_policy_version: number;
10721098
id: string;
10731099
name: string;
10741100
status: HostPolicyResponseActionStatus;

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ describe('EndpointList store concerns', () => {
6363
agentsWithEndpointsTotalError: undefined,
6464
endpointsTotalError: undefined,
6565
queryStrategyVersion: undefined,
66+
policyVersionInfo: undefined,
6667
});
6768
});
6869

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/reducer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const initialEndpointListState: Immutable<EndpointState> = {
4141
endpointsTotal: 0,
4242
endpointsTotalError: undefined,
4343
queryStrategyVersion: undefined,
44+
policyVersionInfo: undefined,
4445
};
4546

4647
/* eslint-disable-next-line complexity */
@@ -55,6 +56,7 @@ export const endpointListReducer: ImmutableReducer<EndpointState, AppAction> = (
5556
request_page_size: pageSize,
5657
request_page_index: pageIndex,
5758
query_strategy_version: queryStrategyVersion,
59+
policy_info: policyVersionInfo,
5860
} = action.payload;
5961
return {
6062
...state,
@@ -63,6 +65,7 @@ export const endpointListReducer: ImmutableReducer<EndpointState, AppAction> = (
6365
pageSize,
6466
pageIndex,
6567
queryStrategyVersion,
68+
policyVersionInfo,
6669
loading: false,
6770
error: undefined,
6871
};
@@ -104,6 +107,7 @@ export const endpointListReducer: ImmutableReducer<EndpointState, AppAction> = (
104107
return {
105108
...state,
106109
details: action.payload.metadata,
110+
policyVersionInfo: action.payload.policy_info,
107111
detailsLoading: false,
108112
detailsError: undefined,
109113
};

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export const isAutoRefreshEnabled = (state: Immutable<EndpointState>) => state.i
5555

5656
export const autoRefreshInterval = (state: Immutable<EndpointState>) => state.autoRefreshInterval;
5757

58+
export const policyVersionInfo = (state: Immutable<EndpointState>) => state.policyVersionInfo;
59+
5860
export const areEndpointsEnrolling = (state: Immutable<EndpointState>) => {
5961
return state.agentsWithEndpointsTotal > state.endpointsTotal;
6062
};

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ export interface EndpointState {
7676
endpointsTotalError?: ServerApiError;
7777
/** The query strategy version that informs whether the transform for KQL is enabled or not */
7878
queryStrategyVersion?: MetadataQueryStrategyVersions;
79+
/** The policy IDs and revision number of the corresponding agent, and endpoint. May be more recent than what's running */
80+
policyVersionInfo?: HostInfo['policy_info'];
7981
}
8082

8183
/**

0 commit comments

Comments
 (0)