Skip to content

Commit 15d185b

Browse files
[9.0] [Cloud Security] Add upgrade agentless deployment background task (#207143) (#218814)
# Backport This will backport the following commits from `main` to `9.0`: - [[Cloud Security] Add upgrade agentless deployment background task (#207143)](#207143) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Lola","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-02-27T01:56:23Z","message":"[Cloud Security] Add upgrade agentless deployment background task (#207143)\n\n## Summary\n\nSummarize your PR. If it involves visual changes include a screenshot or\ngif.\nThis PR add background task to upgrade Agentless Deployments after\nKibana Stack has been upgrade in ESS. Once the Kibana stack upgrades, the task will do following:\n1. Fetch agentless policies with package policies that have agents\n2. Check if agentless agents version is upgradeable by use `semverLT`\nwhich see if current agent version less than latest available upgrade\nversion and current kibana version\n3. If agent version is upgradedable, then task will calls Agentless\nUpgrade Endpoint to upgrade agentless deployment.\n4. Agent should be upgraded to latest available upgraded version\n\n\n![image](https://github.com/user-attachments/assets/e1ad05bf-469e-4eb8-bef0-b4e2edcbb0a0)\n\n\n**How to test PR:**\n\nPrerequisite:\nInstall [QAF\nTool](https://docs.elastic.dev/appex-qa/qaf/getting-started)\nCreate EC cloud api key [QAF Elastic\nCloud](https://docs.elastic.dev/appex-qa/qaf/features/ec-deployments)\n\n1. Go to Elastic Cloud and Create ESS Deployment in `8.17.0-SNAPSHOT`\n```qaf elastic-cloud deployments create --environment production --region gcp-us-west2 --stack-version 8.17.0-SNAPSHOT --version-validation --deployment-name <DEPLOYMENT_NAME> ```\n2. Create an Agentless Integration\n3. Upgrade stack to `8.18.0-SNAPSHOT` > `8.19.0-SNAPSHOT`\n4. Run the following QAF command \n```qaf elastic-cloud deployments upgrade <DEPLOYMENT_NAME>\n9.1.0-SNAPSHOT --kb-docker-image\ndocker.elastic.co/kibana-ci/kibana-cloud:9.1.0-SNAPSHOT-5e00106755e7084d1325e784eb27f91db9724c89```\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>","sha":"f8e31e5fcbb28f485e309fbacf9a2aca9f8d3a2c","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:Fleet","release_note:feature","Team:Cloud Security","backport:prev-minor","ci:cloud-deploy","v9.1.0","v8.19.0","v8.18.1"],"title":"[Cloud Security] Create upgrade agentless deployment background task","number":207143,"url":"https://github.com/elastic/kibana/pull/207143","mergeCommit":{"message":"[Cloud Security] Add upgrade agentless deployment background task (#207143)\n\n## Summary\n\nSummarize your PR. If it involves visual changes include a screenshot or\ngif.\nThis PR add background task to upgrade Agentless Deployments after\nKibana Stack has been upgrade in ESS. Once the Kibana stack upgrades, the task will do following:\n1. Fetch agentless policies with package policies that have agents\n2. Check if agentless agents version is upgradeable by use `semverLT`\nwhich see if current agent version less than latest available upgrade\nversion and current kibana version\n3. If agent version is upgradedable, then task will calls Agentless\nUpgrade Endpoint to upgrade agentless deployment.\n4. Agent should be upgraded to latest available upgraded version\n\n\n![image](https://github.com/user-attachments/assets/e1ad05bf-469e-4eb8-bef0-b4e2edcbb0a0)\n\n\n**How to test PR:**\n\nPrerequisite:\nInstall [QAF\nTool](https://docs.elastic.dev/appex-qa/qaf/getting-started)\nCreate EC cloud api key [QAF Elastic\nCloud](https://docs.elastic.dev/appex-qa/qaf/features/ec-deployments)\n\n1. Go to Elastic Cloud and Create ESS Deployment in `8.17.0-SNAPSHOT`\n```qaf elastic-cloud deployments create --environment production --region gcp-us-west2 --stack-version 8.17.0-SNAPSHOT --version-validation --deployment-name <DEPLOYMENT_NAME> ```\n2. Create an Agentless Integration\n3. Upgrade stack to `8.18.0-SNAPSHOT` > `8.19.0-SNAPSHOT`\n4. Run the following QAF command \n```qaf elastic-cloud deployments upgrade <DEPLOYMENT_NAME>\n9.1.0-SNAPSHOT --kb-docker-image\ndocker.elastic.co/kibana-ci/kibana-cloud:9.1.0-SNAPSHOT-5e00106755e7084d1325e784eb27f91db9724c89```\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>","sha":"f8e31e5fcbb28f485e309fbacf9a2aca9f8d3a2c"}},"sourceBranch":"main","suggestedTargetBranches":["8.18"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/207143","number":207143,"mergeCommit":{"message":"[Cloud Security] Add upgrade agentless deployment background task (#207143)\n\n## Summary\n\nSummarize your PR. If it involves visual changes include a screenshot or\ngif.\nThis PR add background task to upgrade Agentless Deployments after\nKibana Stack has been upgrade in ESS. Once the Kibana stack upgrades, the task will do following:\n1. Fetch agentless policies with package policies that have agents\n2. Check if agentless agents version is upgradeable by use `semverLT`\nwhich see if current agent version less than latest available upgrade\nversion and current kibana version\n3. If agent version is upgradedable, then task will calls Agentless\nUpgrade Endpoint to upgrade agentless deployment.\n4. Agent should be upgraded to latest available upgraded version\n\n\n![image](https://github.com/user-attachments/assets/e1ad05bf-469e-4eb8-bef0-b4e2edcbb0a0)\n\n\n**How to test PR:**\n\nPrerequisite:\nInstall [QAF\nTool](https://docs.elastic.dev/appex-qa/qaf/getting-started)\nCreate EC cloud api key [QAF Elastic\nCloud](https://docs.elastic.dev/appex-qa/qaf/features/ec-deployments)\n\n1. Go to Elastic Cloud and Create ESS Deployment in `8.17.0-SNAPSHOT`\n```qaf elastic-cloud deployments create --environment production --region gcp-us-west2 --stack-version 8.17.0-SNAPSHOT --version-validation --deployment-name <DEPLOYMENT_NAME> ```\n2. Create an Agentless Integration\n3. Upgrade stack to `8.18.0-SNAPSHOT` > `8.19.0-SNAPSHOT`\n4. Run the following QAF command \n```qaf elastic-cloud deployments upgrade <DEPLOYMENT_NAME>\n9.1.0-SNAPSHOT --kb-docker-image\ndocker.elastic.co/kibana-ci/kibana-cloud:9.1.0-SNAPSHOT-5e00106755e7084d1325e784eb27f91db9724c89```\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>","sha":"f8e31e5fcbb28f485e309fbacf9a2aca9f8d3a2c"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/213134","number":213134,"state":"MERGED","mergeCommit":{"sha":"5b98df8f790c2f9212790c1973b54f19c0d18799","message":"[8.x] [Cloud Security] Add upgrade agentless deployment background task (#207143) (#213134)\n\n# Backport\n\nThis will backport the following commits from `main` to `8.x`:\n- [[Cloud Security] Add upgrade agentless deployment background task\n(#207143)](https://github.com/elastic/kibana/pull/207143)\n\n\n\n### Questions ?\nPlease refer to the [Backport tool\ndocumentation](https://github.com/sorenlouv/backport)\n\n\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>"}},{"branch":"8.18","label":"v8.18.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> --------- Co-authored-by: Lola <[email protected]>
1 parent ad3d3e9 commit 15d185b

File tree

10 files changed

+999
-43
lines changed

10 files changed

+999
-43
lines changed

x-pack/platform/plugins/shared/fleet/common/constants/agentless.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,23 @@ export const AGENTLESS_GLOBAL_TAG_NAME_ORGANIZATION = 'organization';
1515
export const AGENTLESS_GLOBAL_TAG_NAME_DIVISION = 'division';
1616
export const AGENTLESS_GLOBAL_TAG_NAME_TEAM = 'team';
1717

18+
export const MAXIMUM_RETRIES = 3;
19+
20+
const HTTP_500_INTERNAL_SERVER_ERROR = 500;
21+
const HTTP_502_BAD_GATEWAY = 502;
22+
const HTTP_503_SERVICE_UNAVAILABLE = 503;
23+
const HTTP_504_GATEWAY_TIMEOUT = 504;
24+
25+
const ECONNREFUSED_CODE = 'ECONNREFUSED';
26+
27+
export const RETRYABLE_HTTP_STATUSES = [
28+
HTTP_500_INTERNAL_SERVER_ERROR,
29+
HTTP_502_BAD_GATEWAY,
30+
HTTP_503_SERVICE_UNAVAILABLE,
31+
HTTP_504_GATEWAY_TIMEOUT,
32+
];
33+
34+
export const RETRYABLE_SERVER_CODES = [ECONNREFUSED_CODE];
1835
// Allowed output types for agentless integrations
1936
export const AGENTLESS_ALLOWED_OUTPUT_TYPES = [outputType.Elasticsearch];
2037

x-pack/platform/plugins/shared/fleet/common/experimental_features.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const _allowedExperimentalValues = {
1111
showExperimentalShipperOptions: false,
1212
useSpaceAwareness: false,
1313
enableAutomaticAgentUpgrades: false,
14+
enabledUpgradeAgentlessDeploymentsTask: false,
1415
};
1516

1617
/**

x-pack/platform/plugins/shared/fleet/server/errors/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ export class AgentlessAgentDeleteError extends FleetError {
6565
super(`Error deleting agentless agent in Fleet, ${message}`);
6666
}
6767
}
68+
69+
export class AgentlessAgentUpgradeError extends FleetError {
70+
constructor(message: string) {
71+
super(`Error upgrading agentless agent in Fleet, ${message}`);
72+
}
73+
}
6874
export class AgentlessAgentConfigError extends FleetError {
6975
constructor(message: string) {
7076
super(`Error validating Agentless API configuration in Fleet, ${message}`);

x-pack/platform/plugins/shared/fleet/server/mocks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ export const createAppContextStartContractMock = (
140140
: {}),
141141
unenrollInactiveAgentsTask: {} as any,
142142
deleteUnenrolledAgentsTask: {} as any,
143+
updateAgentlessDeploymentsTask: {} as any,
143144
};
144145
};
145146

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ import { registerUpgradeManagedPackagePoliciesTask } from './services/setup/mana
147147
import { registerDeployAgentPoliciesTask } from './services/agent_policies/deploy_agent_policies_task';
148148
import { DeleteUnenrolledAgentsTask } from './tasks/delete_unenrolled_agents_task';
149149
import { registerBumpAgentPoliciesTask } from './services/agent_policies/bump_agent_policies_task';
150+
import { UpgradeAgentlessDeploymentsTask } from './tasks/upgrade_agentless_deployment';
150151

151152
export interface FleetSetupDeps {
152153
security: SecurityPluginSetup;
@@ -198,6 +199,7 @@ export interface FleetAppContext {
198199
uninstallTokenService: UninstallTokenServiceInterface;
199200
unenrollInactiveAgentsTask: UnenrollInactiveAgentsTask;
200201
deleteUnenrolledAgentsTask: DeleteUnenrolledAgentsTask;
202+
updateAgentlessDeploymentsTask: UpgradeAgentlessDeploymentsTask;
201203
taskManagerStart?: TaskManagerStartContract;
202204
fetchUsage?: (abortController: AbortController) => Promise<FleetUsage | undefined>;
203205
}
@@ -301,6 +303,7 @@ export class FleetPlugin
301303
private fleetMetricsTask?: FleetMetricsTask;
302304
private unenrollInactiveAgentsTask?: UnenrollInactiveAgentsTask;
303305
private deleteUnenrolledAgentsTask?: DeleteUnenrolledAgentsTask;
306+
private updateAgentlessDeploymentsTask?: UpgradeAgentlessDeploymentsTask;
304307

305308
private agentService?: AgentService;
306309
private packageService?: PackageService;
@@ -648,6 +651,11 @@ export class FleetPlugin
648651
logFactory: this.initializerContext.logger,
649652
});
650653

654+
this.updateAgentlessDeploymentsTask = new UpgradeAgentlessDeploymentsTask({
655+
core,
656+
taskManager: deps.taskManager,
657+
logFactory: this.initializerContext.logger,
658+
});
651659
// Register fields metadata extractors
652660
registerFieldsMetadataExtractors({ core, fieldsMetadata: deps.fieldsMetadata });
653661
}
@@ -694,6 +702,7 @@ export class FleetPlugin
694702
uninstallTokenService,
695703
unenrollInactiveAgentsTask: this.unenrollInactiveAgentsTask!,
696704
deleteUnenrolledAgentsTask: this.deleteUnenrolledAgentsTask!,
705+
updateAgentlessDeploymentsTask: this.updateAgentlessDeploymentsTask!,
697706
taskManagerStart: plugins.taskManager,
698707
fetchUsage: this.fetchUsage,
699708
});
@@ -704,6 +713,11 @@ export class FleetPlugin
704713
this.checkDeletedFilesTask?.start({ taskManager: plugins.taskManager }).catch(() => {});
705714
this.unenrollInactiveAgentsTask?.start({ taskManager: plugins.taskManager }).catch(() => {});
706715
this.deleteUnenrolledAgentsTask?.start({ taskManager: plugins.taskManager }).catch(() => {});
716+
717+
this.updateAgentlessDeploymentsTask
718+
?.start({ taskManager: plugins.taskManager })
719+
.catch(() => {});
720+
707721
startFleetUsageLogger(plugins.taskManager).catch(() => {});
708722
this.fleetMetricsTask
709723
?.start(plugins.taskManager, core.elasticsearch.client.asInternalUser)

x-pack/platform/plugins/shared/fleet/server/services/agents/agentless_agent.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,47 @@ describe('Agentless Agent service', () => {
512512
);
513513
});
514514

515+
it('should upgraded agentless agent for ESS', async () => {
516+
const returnValue = {
517+
id: 'mocked',
518+
regional_id: 'mocked',
519+
};
520+
(axios as jest.MockedFunction<typeof axios>).mockResolvedValueOnce(returnValue);
521+
jest.spyOn(appContextService, 'getConfig').mockReturnValue({
522+
agentless: {
523+
enabled: true,
524+
api: {
525+
url: 'http://api.agentless.com',
526+
tls: {
527+
certificate: '/path/to/cert',
528+
key: '/path/to/key',
529+
ca: '/path/to/ca',
530+
},
531+
},
532+
},
533+
} as any);
534+
jest.spyOn(appContextService, 'getCloud').mockReturnValue({ isCloudEnabled: true } as any);
535+
536+
await agentlessAgentService.upgradeAgentlessDeployment(
537+
'mocked-agentless-agent-policy-id',
538+
'8.17.0'
539+
);
540+
541+
expect(axios).toHaveBeenCalledTimes(1);
542+
543+
expect(axios).toHaveBeenCalledWith(
544+
expect.objectContaining({
545+
headers: expect.anything(),
546+
httpsAgent: expect.anything(),
547+
method: 'PUT',
548+
data: {
549+
stack_version: '8.17.0',
550+
},
551+
url: 'http://api.agentless.com/api/v1/ess/deployments/mocked-agentless-agent-policy-id',
552+
})
553+
);
554+
});
555+
515556
it('should delete agentless agent for serverless', async () => {
516557
const returnValue = {
517558
id: 'mocked',

0 commit comments

Comments
 (0)