From 8080a8c172c10c9ac80e0da8fcd5601e8262f833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 15 Mar 2021 14:56:52 +0100 Subject: [PATCH 01/17] Add `outputPermissions` key to `FullAgentPolicy` --- x-pack/plugins/fleet/common/types/models/agent_policy.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index 7e5b799e484d67..962b52fdd25ae5 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -66,6 +66,13 @@ export interface FullAgentPolicy { [key: string]: any; }; }; + outputPermissions?: { + // FIXME reuse the ES types here, if they exist + [key: string]: Array<{ + names: string[]; + privileges: string[]; + }>; + }; fleet?: { kibana: FullAgentPolicyKibanaConfig; }; From 959f68b3e0532e8cd38494a2e637bd43ea097997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 15 Mar 2021 17:04:44 +0100 Subject: [PATCH 02/17] Use generic in `reduce` --- x-pack/plugins/fleet/server/services/agent_policy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 31c184c598b120..4889f5c0305222 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -655,7 +655,7 @@ class AgentPolicyService { id: agentPolicy.id, outputs: { // TEMPORARY as we only support a default output - ...[defaultOutput].reduce( + ...[defaultOutput].reduce( // eslint-disable-next-line @typescript-eslint/naming-convention (outputs, { config_yaml, name, type, hosts, ca_sha256, api_key }) => { const configJs = config_yaml ? safeLoad(config_yaml) : {}; @@ -675,7 +675,7 @@ class AgentPolicyService { return outputs; }, - {} as FullAgentPolicy['outputs'] + {} ), }, inputs: storedPackagePoliciesToAgentInputs(agentPolicy.package_policies as PackagePolicy[]), From c84d513b32ed51568c0d20ed5fad5573c4f3a466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 15 Mar 2021 17:05:20 +0100 Subject: [PATCH 03/17] Generate `outputPermissions` key in `/full` endpoint --- .../fleet/server/services/agent_policy.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 4889f5c0305222..910fe05fcfa48b 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -698,6 +698,23 @@ class AgentPolicyService { }), }; + // Only add permissions if output.type is "elasticsearch" + fullAgentPolicy.outputPermissions = Object.keys(fullAgentPolicy.outputs).reduce< + NonNullable + >((permissions, outputName) => { + const output = fullAgentPolicy.outputs[outputName]; + if (output && output.type === 'elasticsearch') { + // TODO Extract to a method + permissions[outputName] = [ + { + names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], + privileges: ['auto_configure', 'create_doc'], + }, + ]; + } + return permissions; + }, {}); + // only add settings if not in standalone if (!standalone) { let settings: Settings; From 976c07c53a2564f1e581134ad7092e7bcd7f5c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 15 Mar 2021 17:05:37 +0100 Subject: [PATCH 04/17] Expose `outputPermissions` in the policy yaml --- .../plugins/fleet/common/services/full_agent_policy_to_yaml.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts index e532a90f8839f6..2aaeaf80ce6f17 100644 --- a/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts +++ b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts @@ -16,6 +16,7 @@ const POLICY_KEYS_ORDER = [ 'dataset', 'type', 'outputs', + 'outputPermissions', 'agent', 'inputs', 'enabled', From 7168e440f01f4123afc718025bd7d5149dad57da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 15 Mar 2021 17:23:29 +0100 Subject: [PATCH 05/17] Extract permissions type from `FullAgentPolicy` --- .../plugins/fleet/common/types/models/agent_policy.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index 962b52fdd25ae5..d760e4ec2a9daf 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -59,6 +59,11 @@ export interface FullAgentPolicyInput { [key: string]: any; } +export interface FullAgentPolicyPermission { + names: string[]; + privileges: string[]; +} + export interface FullAgentPolicy { id: string; outputs: { @@ -67,11 +72,7 @@ export interface FullAgentPolicy { }; }; outputPermissions?: { - // FIXME reuse the ES types here, if they exist - [key: string]: Array<{ - names: string[]; - privileges: string[]; - }>; + [key: string]: FullAgentPolicyPermission[]; }; fleet?: { kibana: FullAgentPolicyKibanaConfig; From bf0a6348f1f4cd23dc415bb400f5d283ccd7e763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 15 Mar 2021 17:24:07 +0100 Subject: [PATCH 06/17] Use agent policy permissions to generate the API keys --- .../agents/checkin/state_new_actions.ts | 18 +++++++++++++++--- .../fleet/server/services/api_keys/index.ts | 12 +++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 37320cb24fe3fc..09b194ae7dc8e2 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -40,6 +40,7 @@ import { } from '../actions'; import { appContextService } from '../../app_context'; import { getAgent, updateAgent } from '../crud'; +import type { FullAgentPolicyPermission } from '../../../../common'; import { toPromiseAbortable, AbortError, createRateLimiter } from './rxjs_utils'; @@ -113,14 +114,20 @@ async function getAgentDefaultOutputAPIKey( async function getOrCreateAgentDefaultOutputAPIKey( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - agent: Agent + agent: Agent, + permissions: FullAgentPolicyPermission[] ): Promise { const defaultAPIKey = await getAgentDefaultOutputAPIKey(soClient, esClient, agent); if (defaultAPIKey) { return defaultAPIKey; } - const outputAPIKey = await APIKeysService.generateOutputApiKey(soClient, 'default', agent.id); + const outputAPIKey = await APIKeysService.generateOutputApiKey( + soClient, + 'default', + agent.id, + permissions + ); await updateAgent(esClient, agent.id, { default_api_key: outputAPIKey.key, default_api_key_id: outputAPIKey.id, @@ -168,7 +175,12 @@ export async function createAgentActionFromPolicyAction( ); // Mutate the policy to set the api token for this agent - const apiKey = await getOrCreateAgentDefaultOutputAPIKey(soClient, esClient, agent); + const apiKey = await getOrCreateAgentDefaultOutputAPIKey( + soClient, + esClient, + agent, + newAgentAction.data.policy.outputPermissions.default + ); if (newAgentAction.data.policy) { newAgentAction.data.policy.outputs.default.api_key = apiKey; } diff --git a/x-pack/plugins/fleet/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts index bf229c829fda8f..29858efc79c365 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/index.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/index.ts @@ -8,6 +8,8 @@ import type { KibanaRequest } from 'src/core/server'; import type { SavedObjectsClientContract } from 'src/core/server'; +import type { FullAgentPolicyPermission } from '../../../common'; + import { createAPIKey } from './security'; export { invalidateAPIKeys } from './security'; @@ -16,18 +18,14 @@ export * from './enrollment_api_key'; export async function generateOutputApiKey( soClient: SavedObjectsClientContract, outputId: string, - agentId: string + agentId: string, + permissions: FullAgentPolicyPermission[] ): Promise<{ key: string; id: string }> { const name = `${agentId}:${outputId}`; const key = await createAPIKey(soClient, name, { 'fleet-output': { cluster: ['monitor'], - index: [ - { - names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], - privileges: ['auto_configure', 'create_doc'], - }, - ], + index: permissions, }, }); From 889e16f12478f454226739f1df202dbd2dd65b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Tue, 16 Mar 2021 15:21:03 +0100 Subject: [PATCH 07/17] Fix tests --- .../agents/checkin/state_new_actions.test.ts | 5 +++++ .../services/agents/checkin/state_new_actions.ts | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index daa3992ce5844b..290237e7a8e504 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -144,6 +144,9 @@ describe('test agent checkin new action services', () => { api_key: undefined, }, }, + outputPermissions: { + default: [], + }, inputs: [], }, }, @@ -159,6 +162,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, + outputPermissions: { default: [] }, }, }, id: 'action1', @@ -223,6 +227,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, + outputPermissions: { default: [] }, }, }, id: 'action1', diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 09b194ae7dc8e2..50a6b34453198c 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -174,13 +174,14 @@ export async function createAgentActionFromPolicyAction( } ); + const permissions = + 'policy' in newAgentAction.data + ? newAgentAction.data.policy.outputPermissions.default + : newAgentAction.data.config.outputPermissions.default; // agent <= 7.9 + // Mutate the policy to set the api token for this agent - const apiKey = await getOrCreateAgentDefaultOutputAPIKey( - soClient, - esClient, - agent, - newAgentAction.data.policy.outputPermissions.default - ); + const apiKey = await getOrCreateAgentDefaultOutputAPIKey(soClient, esClient, agent, permissions); + if (newAgentAction.data.policy) { newAgentAction.data.policy.outputs.default.api_key = apiKey; } From 757c38589057c990810d3222f62086cb0efcb474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Tue, 16 Mar 2021 15:21:43 +0100 Subject: [PATCH 08/17] Fix typo --- .../server/services/agents/checkin/state_new_actions.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index 290237e7a8e504..53c392bc87371d 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -217,7 +217,7 @@ describe('test agent checkin new action services', () => { ).toEqual(expectedResult); }); - it('should return CONNFIG_CHANGE and data.config for agent version <= 7.9', async () => { + it('should return CONFIG_CHANGE and data.config for agent version <= 7.9', async () => { const expectedResult = [ { agent_id: 'agent1', From 31381ca80a1d4218acfdb23f379a9a10b29252bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Wed, 17 Mar 2021 17:44:56 +0100 Subject: [PATCH 09/17] Add roles to the output permissions For now we will only have a `fallback` role containing the current permissions. Eventually the permissions needed for each integration will be specified as individual roles. --- .../fleet/common/types/models/agent_policy.ts | 4 +++- .../fleet/server/services/agent_policy.ts | 2 +- .../agents/checkin/state_new_actions.test.ts | 6 +++--- .../agents/checkin/state_new_actions.ts | 2 +- .../fleet/server/services/api_keys/index.ts | 20 +++++++++++++------ 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index d760e4ec2a9daf..c2aa41ddbf787b 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -72,7 +72,9 @@ export interface FullAgentPolicy { }; }; outputPermissions?: { - [key: string]: FullAgentPolicyPermission[]; + [output: string]: { + [role: string]: FullAgentPolicyPermission[]; + }; }; fleet?: { kibana: FullAgentPolicyKibanaConfig; diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 910fe05fcfa48b..19d3b89f4346db 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -705,7 +705,7 @@ class AgentPolicyService { const output = fullAgentPolicy.outputs[outputName]; if (output && output.type === 'elasticsearch') { // TODO Extract to a method - permissions[outputName] = [ + permissions[outputName].fallback = [ { names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], privileges: ['auto_configure', 'create_doc'], diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index 53c392bc87371d..091624d19efd7b 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -145,7 +145,7 @@ describe('test agent checkin new action services', () => { }, }, outputPermissions: { - default: [], + default: { fallback: [] }, }, inputs: [], }, @@ -162,7 +162,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - outputPermissions: { default: [] }, + outputPermissions: { default: { fallback: [] } }, }, }, id: 'action1', @@ -227,7 +227,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - outputPermissions: { default: [] }, + outputPermissions: { default: { fallback: [] } }, }, }, id: 'action1', diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 50a6b34453198c..ae06a26f9873dc 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -115,7 +115,7 @@ async function getOrCreateAgentDefaultOutputAPIKey( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, agent: Agent, - permissions: FullAgentPolicyPermission[] + permissions: { [role: string]: FullAgentPolicyPermission[] } ): Promise { const defaultAPIKey = await getAgentDefaultOutputAPIKey(soClient, esClient, agent); if (defaultAPIKey) { diff --git a/x-pack/plugins/fleet/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts index 29858efc79c365..cfce2d68e49f86 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/index.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/index.ts @@ -19,15 +19,23 @@ export async function generateOutputApiKey( soClient: SavedObjectsClientContract, outputId: string, agentId: string, - permissions: FullAgentPolicyPermission[] + permissions: { [role: string]: FullAgentPolicyPermission[] } ): Promise<{ key: string; id: string }> { const name = `${agentId}:${outputId}`; - const key = await createAPIKey(soClient, name, { - 'fleet-output': { - cluster: ['monitor'], - index: permissions, + + const APIKeyRequest = Object.entries(permissions).reduce>( + (request, [role, indices]) => { + request[role] = { + cluster: ['monitor'], + index: indices, + }; + + return request; }, - }); + {} + ); + + const key = await createAPIKey(soClient, name, APIKeyRequest); if (!key) { throw new Error('Unable to create an output api key'); From 8e5537f0baa8fb144e8ca180bf1a45765e4e8f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 18 Mar 2021 10:55:02 +0100 Subject: [PATCH 10/17] Fix silly mistake --- x-pack/plugins/fleet/server/services/agent_policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 19d3b89f4346db..0681bbf26b5868 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -704,7 +704,7 @@ class AgentPolicyService { >((permissions, outputName) => { const output = fullAgentPolicy.outputs[outputName]; if (output && output.type === 'elasticsearch') { - // TODO Extract to a method + permissions[outputName] = {}; permissions[outputName].fallback = [ { names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], From b9180fc1accfade48bbad27e1f248b9ef1118534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Wed, 24 Mar 2021 14:44:34 +0100 Subject: [PATCH 11/17] use snake_case --- .../fleet/common/services/full_agent_policy_to_yaml.ts | 2 +- x-pack/plugins/fleet/common/types/models/agent_policy.ts | 2 +- x-pack/plugins/fleet/server/services/agent_policy.ts | 4 ++-- .../server/services/agents/checkin/state_new_actions.test.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts index 2aaeaf80ce6f17..a2c1dcd83dd204 100644 --- a/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts +++ b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts @@ -16,7 +16,7 @@ const POLICY_KEYS_ORDER = [ 'dataset', 'type', 'outputs', - 'outputPermissions', + 'output_permissions', 'agent', 'inputs', 'enabled', diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index c2aa41ddbf787b..2558b9835673dd 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -71,7 +71,7 @@ export interface FullAgentPolicy { [key: string]: any; }; }; - outputPermissions?: { + output_permissions?: { [output: string]: { [role: string]: FullAgentPolicyPermission[]; }; diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 9f2d2ceebe48e0..56bbf6153b7891 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -699,8 +699,8 @@ class AgentPolicyService { }; // Only add permissions if output.type is "elasticsearch" - fullAgentPolicy.outputPermissions = Object.keys(fullAgentPolicy.outputs).reduce< - NonNullable + fullAgentPolicy.output_permissions = Object.keys(fullAgentPolicy.outputs).reduce< + NonNullable >((permissions, outputName) => { const output = fullAgentPolicy.outputs[outputName]; if (output && output.type === 'elasticsearch') { diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index 091624d19efd7b..25ad5e68be65bb 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -144,7 +144,7 @@ describe('test agent checkin new action services', () => { api_key: undefined, }, }, - outputPermissions: { + output_permissions: { default: { fallback: [] }, }, inputs: [], From 7a76452dd3c94958c2c3039d114c9f44f9a83871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 25 Mar 2021 10:13:05 +0100 Subject: [PATCH 12/17] Wrap permissions array with an `index` property This should help fleet server to process the payload a bit more efficiently. --- .../fleet/common/types/models/agent_policy.ts | 4 +++- .../plugins/fleet/server/services/agent_policy.ts | 14 ++++++++------ .../agents/checkin/state_new_actions.test.ts | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index 2558b9835673dd..406a37b6766da1 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -73,7 +73,9 @@ export interface FullAgentPolicy { }; output_permissions?: { [output: string]: { - [role: string]: FullAgentPolicyPermission[]; + [role: string]: { + index: FullAgentPolicyPermission[]; + }; }; }; fleet?: { diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 56bbf6153b7891..25e8b312df6d49 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -705,12 +705,14 @@ class AgentPolicyService { const output = fullAgentPolicy.outputs[outputName]; if (output && output.type === 'elasticsearch') { permissions[outputName] = {}; - permissions[outputName].fallback = [ - { - names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], - privileges: ['auto_configure', 'create_doc'], - }, - ]; + permissions[outputName].fallback = { + index: [ + { + names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], + privileges: ['auto_configure', 'create_doc'], + }, + ], + }; } return permissions; }, {}); diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index 25ad5e68be65bb..d08c926f84ce7c 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -145,7 +145,7 @@ describe('test agent checkin new action services', () => { }, }, output_permissions: { - default: { fallback: [] }, + default: { fallback: { index: [] } }, }, inputs: [], }, From 95e8afd53940ab2f1e5c4e4f643d6e384479c0c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 25 Mar 2021 10:14:21 +0100 Subject: [PATCH 13/17] Fix types --- .../server/services/agents/checkin/state_new_actions.test.ts | 4 ++-- .../fleet/server/services/agents/checkin/state_new_actions.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index d08c926f84ce7c..88298a6fb11843 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -162,7 +162,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - outputPermissions: { default: { fallback: [] } }, + output_permissions: { default: { fallback: [] } }, }, }, id: 'action1', @@ -227,7 +227,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - outputPermissions: { default: { fallback: [] } }, + output_permissions: { default: { fallback: [] } }, }, }, id: 'action1', diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 9b04352faa2340..b6de04a05387cd 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -176,8 +176,8 @@ export async function createAgentActionFromPolicyAction( const permissions = 'policy' in newAgentAction.data - ? newAgentAction.data.policy.outputPermissions.default - : newAgentAction.data.config.outputPermissions.default; // agent <= 7.9 + ? newAgentAction.data.policy.output_permissions.default + : newAgentAction.data.config.output_permissions.default; // agent <= 7.9 // Mutate the policy to set the api token for this agent const apiKey = await getOrCreateAgentDefaultOutputAPIKey(soClient, esClient, agent, permissions); From 6a43367018f488d56899c282c6c01c013a529445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 25 Mar 2021 10:39:31 +0100 Subject: [PATCH 14/17] fixup! Wrap permissions array with an `index` property --- .../agents/checkin/state_new_actions.ts | 4 ++-- .../fleet/server/services/api_keys/index.ts | 21 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index b6de04a05387cd..257c1ea41d45b9 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -115,7 +115,7 @@ async function getOrCreateAgentDefaultOutputAPIKey( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, agent: Agent, - permissions: { [role: string]: FullAgentPolicyPermission[] } + permissions: { [role: string]: { index: FullAgentPolicyPermission[] } } ): Promise { const defaultAPIKey = await getAgentDefaultOutputAPIKey(soClient, esClient, agent); if (defaultAPIKey) { @@ -174,7 +174,7 @@ export async function createAgentActionFromPolicyAction( } ); - const permissions = + const permissions: { [role: string]: { index: FullAgentPolicyPermission[] } } = 'policy' in newAgentAction.data ? newAgentAction.data.policy.output_permissions.default : newAgentAction.data.config.output_permissions.default; // agent <= 7.9 diff --git a/x-pack/plugins/fleet/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts index cfce2d68e49f86..a46749a2f95639 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/index.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/index.ts @@ -19,21 +19,20 @@ export async function generateOutputApiKey( soClient: SavedObjectsClientContract, outputId: string, agentId: string, - permissions: { [role: string]: FullAgentPolicyPermission[] } + permissions: { [role: string]: { index: FullAgentPolicyPermission[] } } ): Promise<{ key: string; id: string }> { const name = `${agentId}:${outputId}`; - const APIKeyRequest = Object.entries(permissions).reduce>( - (request, [role, indices]) => { - request[role] = { - cluster: ['monitor'], - index: indices, - }; + const APIKeyRequest = Object.entries(permissions).reduce< + Record + >((request, [role, indices]) => { + request[role] = { + cluster: ['monitor'], + ...indices, + }; - return request; - }, - {} - ); + return request; + }, {}); const key = await createAPIKey(soClient, name, APIKeyRequest); From 3831a8aed18f7059ebc0a2c9f9b81624afc3b6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 25 Mar 2021 10:40:35 +0100 Subject: [PATCH 15/17] Rename fallback role to `_fallback` --- x-pack/plugins/fleet/server/services/agent_policy.ts | 2 +- .../services/agents/checkin/state_new_actions.test.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 25e8b312df6d49..3b90a662cae8e0 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -705,7 +705,7 @@ class AgentPolicyService { const output = fullAgentPolicy.outputs[outputName]; if (output && output.type === 'elasticsearch') { permissions[outputName] = {}; - permissions[outputName].fallback = { + permissions[outputName]._fallback = { index: [ { names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index 88298a6fb11843..b474d54a545a7a 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -145,7 +145,7 @@ describe('test agent checkin new action services', () => { }, }, output_permissions: { - default: { fallback: { index: [] } }, + default: { _fallback: { index: [] } }, }, inputs: [], }, @@ -162,7 +162,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - output_permissions: { default: { fallback: [] } }, + output_permissions: { default: { _fallback: [] } }, }, }, id: 'action1', @@ -227,7 +227,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - output_permissions: { default: { fallback: [] } }, + output_permissions: { default: { _fallback: [] } }, }, }, id: 'action1', From 4f52c281ac22f0f3acf8972caaf19a22ad8149c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 25 Mar 2021 14:32:44 +0100 Subject: [PATCH 16/17] s/index/indices/g --- x-pack/plugins/fleet/common/types/models/agent_policy.ts | 2 +- x-pack/plugins/fleet/server/services/agent_policy.ts | 2 +- .../services/agents/checkin/state_new_actions.test.ts | 6 +++--- .../server/services/agents/checkin/state_new_actions.ts | 4 ++-- x-pack/plugins/fleet/server/services/api_keys/index.ts | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index 406a37b6766da1..309bb690167288 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -74,7 +74,7 @@ export interface FullAgentPolicy { output_permissions?: { [output: string]: { [role: string]: { - index: FullAgentPolicyPermission[]; + indices: FullAgentPolicyPermission[]; }; }; }; diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 3b90a662cae8e0..bf26921f0ab148 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -706,7 +706,7 @@ class AgentPolicyService { if (output && output.type === 'elasticsearch') { permissions[outputName] = {}; permissions[outputName]._fallback = { - index: [ + indices: [ { names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], privileges: ['auto_configure', 'create_doc'], diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index b474d54a545a7a..ca43079b86e3f5 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -145,7 +145,7 @@ describe('test agent checkin new action services', () => { }, }, output_permissions: { - default: { _fallback: { index: [] } }, + default: { _fallback: { indices: [] } }, }, inputs: [], }, @@ -162,7 +162,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - output_permissions: { default: { _fallback: [] } }, + output_permissions: { default: { _fallback: { indices: [] } } }, }, }, id: 'action1', @@ -227,7 +227,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - output_permissions: { default: { _fallback: [] } }, + output_permissions: { default: { _fallback: { indices: [] } } }, }, }, id: 'action1', diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 257c1ea41d45b9..4e6208dbb0a377 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -115,7 +115,7 @@ async function getOrCreateAgentDefaultOutputAPIKey( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, agent: Agent, - permissions: { [role: string]: { index: FullAgentPolicyPermission[] } } + permissions: { [role: string]: { indices: FullAgentPolicyPermission[] } } ): Promise { const defaultAPIKey = await getAgentDefaultOutputAPIKey(soClient, esClient, agent); if (defaultAPIKey) { @@ -174,7 +174,7 @@ export async function createAgentActionFromPolicyAction( } ); - const permissions: { [role: string]: { index: FullAgentPolicyPermission[] } } = + const permissions: { [role: string]: { indices: FullAgentPolicyPermission[] } } = 'policy' in newAgentAction.data ? newAgentAction.data.policy.output_permissions.default : newAgentAction.data.config.output_permissions.default; // agent <= 7.9 diff --git a/x-pack/plugins/fleet/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts index a46749a2f95639..b0c14c7a7063fb 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/index.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/index.ts @@ -19,12 +19,12 @@ export async function generateOutputApiKey( soClient: SavedObjectsClientContract, outputId: string, agentId: string, - permissions: { [role: string]: { index: FullAgentPolicyPermission[] } } + permissions: { [role: string]: { indices: FullAgentPolicyPermission[] } } ): Promise<{ key: string; id: string }> { const name = `${agentId}:${outputId}`; const APIKeyRequest = Object.entries(permissions).reduce< - Record + Record >((request, [role, indices]) => { request[role] = { cluster: ['monitor'], From 9d488d49f5598c04948653fea516c2481a2099a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Mon, 29 Mar 2021 13:26:49 +0200 Subject: [PATCH 17/17] Add `cluster` prop to agent policy --- .../fleet/common/types/models/agent_policy.ts | 17 +++++++------- .../fleet/server/services/agent_policy.ts | 1 + .../agents/checkin/state_new_actions.test.ts | 6 ++--- .../agents/checkin/state_new_actions.ts | 23 ++++++++----------- .../fleet/server/services/api_keys/index.ts | 18 +++------------ 5 files changed, 26 insertions(+), 39 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index 309bb690167288..07a9088f1f36d8 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -59,9 +59,14 @@ export interface FullAgentPolicyInput { [key: string]: any; } -export interface FullAgentPolicyPermission { - names: string[]; - privileges: string[]; +export interface FullAgentPolicyOutputPermissions { + [role: string]: { + cluster: string[]; + indices: Array<{ + names: string[]; + privileges: string[]; + }>; + }; } export interface FullAgentPolicy { @@ -72,11 +77,7 @@ export interface FullAgentPolicy { }; }; output_permissions?: { - [output: string]: { - [role: string]: { - indices: FullAgentPolicyPermission[]; - }; - }; + [output: string]: FullAgentPolicyOutputPermissions; }; fleet?: { kibana: FullAgentPolicyKibanaConfig; diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index bf26921f0ab148..18d53a53519dd9 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -706,6 +706,7 @@ class AgentPolicyService { if (output && output.type === 'elasticsearch') { permissions[outputName] = {}; permissions[outputName]._fallback = { + cluster: ['monitor'], indices: [ { names: ['logs-*', 'metrics-*', 'traces-*', '.logs-endpoint.diagnostic.collection-*'], diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index ca43079b86e3f5..12205f31106144 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -145,7 +145,7 @@ describe('test agent checkin new action services', () => { }, }, output_permissions: { - default: { _fallback: { indices: [] } }, + default: { _fallback: { cluster: [], indices: [] } }, }, inputs: [], }, @@ -162,7 +162,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - output_permissions: { default: { _fallback: { indices: [] } } }, + output_permissions: { default: { _fallback: { cluster: [], indices: [] } } }, }, }, id: 'action1', @@ -227,7 +227,7 @@ describe('test agent checkin new action services', () => { id: 'policy1', inputs: [], outputs: { default: { api_key: 'MOCK_API_KEY', hosts: [], type: 'elasticsearch' } }, - output_permissions: { default: { _fallback: { indices: [] } } }, + output_permissions: { default: { _fallback: { cluster: [], indices: [] } } }, }, }, id: 'action1', diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 6e372432da4bcc..8f0000413471f3 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -40,7 +40,7 @@ import { } from '../actions'; import { appContextService } from '../../app_context'; import { updateAgent } from '../crud'; -import type { FullAgentPolicyPermission } from '../../../../common'; +import type { FullAgentPolicy, FullAgentPolicyOutputPermissions } from '../../../../common'; import { toPromiseAbortable, AbortError, createRateLimiter } from './rxjs_utils'; @@ -115,7 +115,7 @@ async function getOrCreateAgentDefaultOutputAPIKey( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, agent: Agent, - permissions: { [role: string]: { indices: FullAgentPolicyPermission[] } } + permissions: FullAgentPolicyOutputPermissions ): Promise { const defaultAPIKey = await getAgentDefaultOutputAPIKey(soClient, esClient, agent); if (defaultAPIKey) { @@ -174,21 +174,18 @@ export async function createAgentActionFromPolicyAction( } ); - const permissions: { [role: string]: { indices: FullAgentPolicyPermission[] } } = - 'policy' in newAgentAction.data - ? newAgentAction.data.policy.output_permissions.default - : newAgentAction.data.config.output_permissions.default; // agent <= 7.9 + // agent <= 7.9 uses `data.config` instead of `data.policy` + const policyProp = 'policy' in newAgentAction.data ? 'policy' : 'config'; + + // TODO: The null assertion `!` is strictly correct for the current use case + // where the only output is `elasticsearch`, but this might change in the future. + const permissions = (newAgentAction.data[policyProp] as FullAgentPolicy).output_permissions! + .default; // Mutate the policy to set the api token for this agent const apiKey = await getOrCreateAgentDefaultOutputAPIKey(soClient, esClient, agent, permissions); - if (newAgentAction.data.policy) { - newAgentAction.data.policy.outputs.default.api_key = apiKey; - } - // BWC for agent <= 7.9 - else if (newAgentAction.data.config) { - newAgentAction.data.config.outputs.default.api_key = apiKey; - } + newAgentAction.data[policyProp].outputs.default.api_key = apiKey; return [newAgentAction]; } diff --git a/x-pack/plugins/fleet/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts index b0c14c7a7063fb..1f9e77821360c2 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/index.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/index.ts @@ -8,7 +8,7 @@ import type { KibanaRequest } from 'src/core/server'; import type { SavedObjectsClientContract } from 'src/core/server'; -import type { FullAgentPolicyPermission } from '../../../common'; +import type { FullAgentPolicyOutputPermissions } from '../../../common'; import { createAPIKey } from './security'; @@ -19,22 +19,10 @@ export async function generateOutputApiKey( soClient: SavedObjectsClientContract, outputId: string, agentId: string, - permissions: { [role: string]: { indices: FullAgentPolicyPermission[] } } + permissions: FullAgentPolicyOutputPermissions ): Promise<{ key: string; id: string }> { const name = `${agentId}:${outputId}`; - - const APIKeyRequest = Object.entries(permissions).reduce< - Record - >((request, [role, indices]) => { - request[role] = { - cluster: ['monitor'], - ...indices, - }; - - return request; - }, {}); - - const key = await createAPIKey(soClient, name, APIKeyRequest); + const key = await createAPIKey(soClient, name, permissions); if (!key) { throw new Error('Unable to create an output api key');