Skip to content

Commit

Permalink
improve policy logic
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelolo24 committed Jul 15, 2020
1 parent a9c2095 commit ee5dca9
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 62 deletions.
4 changes: 2 additions & 2 deletions x-pack/plugins/security_solution/server/usage/collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export const registerCollector: RegisterCollector = ({
},
policies: {
malware: {
success: { type: 'long' },
warning: { type: 'long' },
active: { type: 'long' },
inactive: { type: 'long' },
failure: { type: 'long' },
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,55 @@ const mockPolicyPayload = (malwareStatus: 'success' | 'warning' | 'failure') =>
JSON.stringify({
'endpoint-security': {
Endpoint: {
configuration: {
inputs: [
{
id: '0d466df0-c60f-11ea-a5c5-151665e785c4',
policy: {
linux: {
events: {
file: true,
network: true,
process: true,
},
logging: {
file: 'info',
},
},
mac: {
events: {
file: true,
network: true,
process: true,
},
logging: {
file: 'info',
},
malware: {
mode: 'prevent',
},
},
windows: {
events: {
dll_and_driver_load: true,
dns: true,
file: true,
network: true,
process: true,
registry: true,
security: true,
},
logging: {
file: 'info',
},
malware: {
mode: 'prevent',
},
},
},
},
],
},
policy: {
applied: {
id: '0d466df0-c60f-11ea-a5c5-151665e785c4',
Expand Down Expand Up @@ -114,6 +163,18 @@ const mockPolicyPayload = (malwareStatus: 'success' | 'warning' | 'failure') =>
id: 'testAgentId',
version: '8.0.0-SNAPSHOT',
},
host: {
architecture: 'x86_64',
id: 'a4148b63-1758-ab1f-a6d3-f95075cb1a9c',
os: {
Ext: {
variant: 'Windows 10 Pro',
},
full: 'Windows 10 Pro 2004 (10.0.19041.329)',
name: 'Windows',
version: '2004 (10.0.19041.329)',
},
},
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ describe('test security solution endpoint telemetry', () => {
"os": Array [],
"policies": Object {
"malware": Object {
"active": 0,
"failure": 0,
"success": 0,
"warning": 0,
"inactive": 0,
},
},
"total_installed": 0,
Expand All @@ -68,8 +68,8 @@ describe('test security solution endpoint telemetry', () => {
policies: {
malware: {
failure: 0,
success: 0,
warning: 0,
active: 0,
inactive: 0,
},
},
});
Expand Down Expand Up @@ -102,8 +102,8 @@ describe('test security solution endpoint telemetry', () => {
policies: {
malware: {
failure: 1,
success: 0,
warning: 0,
active: 0,
inactive: 0,
},
},
});
Expand Down Expand Up @@ -134,8 +134,8 @@ describe('test security solution endpoint telemetry', () => {
policies: {
malware: {
failure: 0,
success: 1,
warning: 0,
active: 1,
inactive: 0,
},
},
});
Expand Down
147 changes: 97 additions & 50 deletions x-pack/plugins/security_solution/server/usage/endpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ export interface AgentOSMetadataTelemetry {
version: string;
count: number;
}

export type PolicyTypes = 'malware';
export interface PolicyTelemetry {
success: number;
warning: number;
active: number;
inactive: number;
failure: number;
}

export type PoliciesTelemetry = Record<PolicyTypes, PolicyTelemetry>;
export interface PoliciesTelemetry {
malware: PolicyTelemetry;
}

export interface EndpointUsage {
total_installed: number;
Expand All @@ -31,6 +31,8 @@ export interface EndpointUsage {
policies: PoliciesTelemetry;
}

type EndpointOSNames = 'Linux' | 'Windows' | 'macOs';

export interface AgentLocalMetadata extends AgentMetadata {
elastic: {
agent: {
Expand All @@ -48,8 +50,8 @@ export interface AgentLocalMetadata extends AgentMetadata {
};
}

export type OSTracker = Record<string, AgentOSMetadataTelemetry>;

type OSTracker = Record<string, AgentOSMetadataTelemetry>;
type AgentDailyActiveTracker = Map<string, boolean>;
/**
* @description returns an empty telemetry object to be incrmented and updated within the `getEndpointTelemetryFromFleet` fn
*/
Expand All @@ -59,13 +61,16 @@ export const getDefaultEndpointTelemetry = (): EndpointUsage => ({
os: [],
policies: {
malware: {
success: 0,
warning: 0,
active: 0,
inactive: 0,
failure: 0,
},
},
});

/**
* @description this fun
*/
export const trackEndpointOSTelemetry = (
os: AgentLocalMetadata['os'],
osTracker: OSTracker
Expand All @@ -87,6 +92,80 @@ export const trackEndpointOSTelemetry = (
return updatedOSTracker;
};

/**
* @description This iterates over all unique agents that currently track an endpoint package. It takes a list of agents who have checked in in the last 24 hours
* and then checks whether those agents have endpoints whose latest status is 'RUNNING' to determine an active_within_last_24_hours. Since the policy information is also tracked in these events
* we pull out the status of the current protection (malware) type. This must be done in a compound manner as the desired status is reflected in the config, and the successful application of that policy
* is tracked in the policy.applied.response.configurations[protectionsType].status. Using these two we can determine whether the policy is toggled on, off, or failed to turn on.
*/
export const addEndpointDailyActivityAndPolicyDetailsToTelemetry = async (
agentDailyActiveTracker: AgentDailyActiveTracker,
savedObjectsClient: ISavedObjectsRepository,
endpointTelemetry: EndpointUsage
): Promise<EndpointUsage> => {
const updatedEndpointTelemetry = { ...endpointTelemetry };

const policyHostTypeToPolicyType = {
Linux: 'linux',
macOs: 'mac',
Windows: 'windows',
};
const enabledMalwarePolicyTypes = ['prevent', 'detect'];

for (const agentId of agentDailyActiveTracker.keys()) {
const { saved_objects: agentEvents } = await getLatestFleetEndpointEvent(
savedObjectsClient,
agentId
);

const latestEndpointEvent = agentEvents[0];
if (latestEndpointEvent) {
/*
We can assume that if the last status of the endpoint is RUNNING and the agent has checked in within the last 24 hours
then the endpoint has still been running within the last 24 hours.
*/
const { subtype, payload } = latestEndpointEvent.attributes;
const endpointIsActive =
subtype === 'RUNNING' && agentDailyActiveTracker.get(agentId) === true;

if (endpointIsActive) {
updatedEndpointTelemetry.active_within_last_24_hours += 1;
}

// The policy details are sent as a string on the 'payload' attribute of the agent event
const endpointPolicyDetails = payload ? JSON.parse(payload) : null;
if (endpointPolicyDetails) {
// We get the setting the user desired to enable (treating prevent and detect as 'active' states) and then see if it succeded or failed.
const hostType =
policyHostTypeToPolicyType[
endpointPolicyDetails['endpoint-security']?.host?.os?.name as EndpointOSNames
];
const userDesiredMalwareState =
endpointPolicyDetails['endpoint-security'].Endpoint?.configuration?.inputs[0]?.policy[
hostType
]?.malware?.mode;

const isAnActiveMalwareState = enabledMalwarePolicyTypes.includes(userDesiredMalwareState);
const malwareStatus =
endpointPolicyDetails['endpoint-security'].Endpoint?.policy?.applied?.response
?.configurations?.malware?.status;

if (isAnActiveMalwareState && malwareStatus !== 'failure') {
updatedEndpointTelemetry.policies.malware.active += 1;
}
if (!isAnActiveMalwareState) {
updatedEndpointTelemetry.policies.malware.inactive += 1;
}
if (isAnActiveMalwareState && malwareStatus === 'failure') {
updatedEndpointTelemetry.policies.malware.failure += 1;
}
}
}
}

return updatedEndpointTelemetry;
};

/**
* @description This aggregates the telemetry details from the two fleet savedObject sources, `fleet-agents` and `fleet-agent-events` to populate
* the telemetry details for endpoint. Since we cannot access our own indices due to `kibana_system` not having access, this is the best alternative.
Expand All @@ -106,7 +185,7 @@ export const getEndpointTelemetryFromFleet = async (
// Use unique hosts to prevent any potential duplicates
const uniqueHostIds: Set<string> = new Set();
// Need agents to get events data for those that have run in last 24 hours as well as policy details
const agentDailyActiveTracker: Map<string, boolean> = new Map();
const agentDailyActiveTracker: AgentDailyActiveTracker = new Map();

const aDayAgo = new Date();
aDayAgo.setDate(aDayAgo.getDate() - 1);
Expand All @@ -131,48 +210,16 @@ export const getEndpointTelemetryFromFleet = async (
endpointTelemetry
);

// All unique agents with an endpoint installed. You can technically install a new agent on a host, so relying on most recently installed.
// All unique hosts with an endpoint installed.
endpointTelemetry.total_installed = uniqueHostIds.size;
// Get the objects to populate our OS Telemetry
endpointMetadataTelemetry.os = Object.values(osTracker);
// Populate endpoint telemetry with the finalized 24 hour count and policy details
const finalizedEndpointTelemetryData = await addEndpointDailyActivityAndPolicyDetailsToTelemetry(
agentDailyActiveTracker,
savedObjectsClient,
endpointMetadataTelemetry
);

for (const agentId of agentDailyActiveTracker.keys()) {
const { saved_objects: agentEvents } = await getLatestFleetEndpointEvent(
savedObjectsClient,
agentId
);

const latestEndpointEvent = agentEvents[0];
if (latestEndpointEvent) {
/*
We can assume that if the last status of the endpoint is RUNNING and the agent has checked in within the last 24 hours
then the endpoint has still been running within the last 24 hours.
*/
const { subtype, payload } = latestEndpointEvent.attributes;
const endpointIsActive =
subtype === 'RUNNING' && agentDailyActiveTracker.get(agentId) === true;

if (endpointIsActive) {
endpointMetadataTelemetry.active_within_last_24_hours += 1;
}
const endpointPolicyDetails = payload ? JSON.parse(payload) : null;
if (endpointPolicyDetails) {
const malwareStatus =
endpointPolicyDetails['endpoint-security'].Endpoint?.policy?.applied?.response
?.configurations?.malware?.status;

if (malwareStatus === 'success') {
endpointMetadataTelemetry.policies.malware.success += 1;
}
if (malwareStatus === 'warning') {
endpointMetadataTelemetry.policies.malware.warning += 1;
}
if (malwareStatus === 'failure') {
endpointMetadataTelemetry.policies.malware.failure += 1;
}
}
}
}

return endpointMetadataTelemetry;
return finalizedEndpointTelemetryData;
};
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@
"properties": {
"malware": {
"properties": {
"success": {
"active": {
"type": "long"
},
"warning": {
"inactive": {
"type": "long"
},
"failure": {
Expand Down

0 comments on commit ee5dca9

Please sign in to comment.