diff --git a/oas_docs/bundle.json b/oas_docs/bundle.json index 325b49428dc56..74fdb243d3abd 100644 --- a/oas_docs/bundle.json +++ b/oas_docs/bundle.json @@ -10919,6 +10919,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -11924,6 +11939,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -12226,6 +12256,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -13257,6 +13302,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -14534,6 +14594,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -15537,6 +15612,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -15842,6 +15932,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -16873,6 +16978,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { diff --git a/oas_docs/bundle.serverless.json b/oas_docs/bundle.serverless.json index b145f66ca7e52..93c4239ca4ad6 100644 --- a/oas_docs/bundle.serverless.json +++ b/oas_docs/bundle.serverless.json @@ -10919,6 +10919,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -11924,6 +11939,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -12226,6 +12256,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -13257,6 +13302,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -14534,6 +14594,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -15537,6 +15612,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -15842,6 +15932,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { @@ -16873,6 +16978,21 @@ "agentless": { "additionalProperties": false, "properties": { + "cloud_connectors": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "target_csp": { + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, "resources": { "additionalProperties": false, "properties": { diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index 319729753016f..6ac44dedc0e33 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -16677,6 +16677,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -17349,6 +17359,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -17560,6 +17580,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -18251,6 +18281,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -18921,6 +18961,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -19591,6 +19641,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -19804,6 +19864,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -20494,6 +20564,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index fedb3a14c3333..54a56cce1402c 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -18919,6 +18919,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -19591,6 +19601,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -19802,6 +19822,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -20493,6 +20523,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -21163,6 +21203,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -21833,6 +21883,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -22046,6 +22106,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object @@ -22736,6 +22806,16 @@ paths: additionalProperties: false type: object properties: + cloud_connectors: + additionalProperties: false + type: object + properties: + enabled: + type: boolean + target_csp: + type: string + required: + - enabled resources: additionalProperties: false type: object diff --git a/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts index baf0037c00c19..a500dccaf3a34 100644 --- a/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/common/types/models/agent_policy.ts @@ -73,7 +73,12 @@ export interface AgentTargetVersion { percentage: number; } +export interface CloudConnectors { + target_csp?: string; + enabled?: boolean; +} export interface AgentlessPolicy { + cloud_connectors?: CloudConnectors; resources?: { requests?: { memory?: string; diff --git a/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts b/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts index 8712d9cf6ed24..912cf1e6ed87b 100644 --- a/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts +++ b/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts @@ -14,7 +14,7 @@ import type { monitoringTypes, installationStatuses, } from '../../constants'; -import type { ValueOf } from '..'; +import type { CloudConnectors, ValueOf } from '..'; import type { PackageSpecManifest, PackageSpecIcon, PackageSpecCategory } from './package_spec'; @@ -204,6 +204,7 @@ export interface DeploymentsModesAgentless extends DeploymentsModesDefault { organization?: string; division?: string; team?: string; + cloud_connectors?: CloudConnectors; resources?: { requests: { cpu: string; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts index 41c84ddcc3d12..381dcecffa0e7 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts @@ -398,6 +398,127 @@ describe('Agentless Agent service', () => { ); }); + it('should create agentless agent with cloud_connectors', async () => { + const returnValue = { + id: 'mocked', + regional_id: 'mocked', + }; + + (axios as jest.MockedFunction).mockResolvedValueOnce(returnValue); + const soClient = getAgentPolicyCreateMock(); + // ignore unrelated unique name constraint + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + jest.spyOn(appContextService, 'getConfig').mockReturnValue({ + agentless: { + enabled: true, + api: { + url: 'http://api.agentless.com', + tls: { + certificate: '/path/to/cert', + key: '/path/to/key', + ca: '/path/to/ca', + }, + }, + }, + } as any); + jest + .spyOn(appContextService, 'getCloud') + .mockReturnValue({ isCloudEnabled: true, isServerlessEnabled: true } as any); + jest + .spyOn(appContextService, 'getKibanaVersion') + .mockReturnValue('mocked-kibana-version-infinite'); + mockedFleetServerHostService.list.mockResolvedValue({ + items: [ + { + id: 'mocked-fleet-server-id', + host: 'http://fleetserver:8220', + active: true, + is_default: true, + host_urls: ['http://fleetserver:8220'], + }, + ], + } as any); + mockedListEnrollmentApiKeys.mockResolvedValue({ + items: [ + { + id: 'mocked-fleet-enrollment-token-id', + policy_id: 'mocked-fleet-enrollment-policy-id', + api_key: 'mocked-fleet-enrollment-api-key', + }, + ], + } as any); + + const createAgentlessAgentReturnValue = await agentlessAgentService.createAgentlessAgent( + esClient, + soClient, + { + id: 'mocked-agentless-agent-policy-id', + name: 'agentless agent policy', + namespace: 'default', + supports_agentless: true, + agentless: { + resources: { + requests: { + memory: '1Gi', + cpu: '500m', + }, + }, + cloud_connectors: { + target_csp: 'aws', + enabled: true, + }, + }, + global_data_tags: [ + { + name: 'organization', + value: 'elastic', + }, + { + name: 'division', + value: 'cloud', + }, + { + name: 'team', + value: 'fleet', + }, + ], + } as AgentPolicy + ); + + expect(axios).toHaveBeenCalledTimes(1); + expect(createAgentlessAgentReturnValue).toEqual(returnValue); + expect(axios).toHaveBeenCalledWith( + expect.objectContaining({ + data: { + fleet_token: 'mocked-fleet-enrollment-api-key', + fleet_url: 'http://fleetserver:8220', + policy_id: 'mocked-agentless-agent-policy-id', + resources: { + requests: { + memory: '1Gi', + cpu: '500m', + }, + }, + cloud_connectors: { + target_csp: 'aws', + enabled: true, + }, + labels: { + owner: { + org: 'elastic', + division: 'cloud', + team: 'fleet', + }, + }, + }, + headers: expect.anything(), + httpsAgent: expect.anything(), + method: 'POST', + url: 'http://api.agentless.com/api/v1/serverless/deployments', + }) + ); + }); + it('should create agentless agent when no labels are given', async () => { const returnValue = { id: 'mocked', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts index 76da7ebb06e95..db46efeeda7c6 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.ts @@ -102,6 +102,12 @@ class AgentlessAgentService { `[Agentless API] Creating agentless agent with fleetUrl ${fleetUrl} and fleet_token: [REDACTED]` ); + if (agentlessAgentPolicy.agentless?.cloud_connectors?.enabled) { + logger.debug( + `[Agentless API] Creating agentless agent with ${agentlessAgentPolicy.agentless?.cloud_connectors?.target_csp} cloud connector enabled for agentless policy ${policyId}` + ); + } + logger.debug( `[Agentless API] Creating agentless agent with TLS cert: ${ agentlessConfig?.api?.tls?.certificate ? '[REDACTED]' : 'undefined' @@ -119,6 +125,7 @@ class AgentlessAgentService { fleet_url: fleetUrl, fleet_token: fleetToken, resources: agentlessAgentPolicy.agentless?.resources, + cloud_connectors: agentlessAgentPolicy.agentless?.cloud_connectors, labels, }, method: 'POST', diff --git a/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts index e5e6007d292a0..7292b6bba7322 100644 --- a/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/types/models/agent_policy.ts @@ -53,6 +53,13 @@ function validateCPU(s: string) { } } +function validateCloudProvider(s: string) { + const csps = ['aws', 'azure', 'gcp']; + if (!csps.includes(s)) { + return 'Invalid cloud provider'; + } +} + export const AgentPolicyBaseSchema = { id: schema.maybe(schema.string()), space_ids: schema.maybe(schema.arrayOf(schema.string())), @@ -148,6 +155,12 @@ export const AgentPolicyBaseSchema = { ), agentless: schema.maybe( schema.object({ + cloud_connectors: schema.maybe( + schema.object({ + target_csp: schema.maybe(schema.string({ validate: validateCloudProvider })), + enabled: schema.boolean(), + }) + ), resources: schema.maybe( schema.object({ requests: schema.maybe(