[Fleet] Prevent agents from enrolling in a managed policy (#90458)
## Summary Add guard to `/agents/enroll` API preventing agents from enrolling in managed policies closes #90435 - [x] No Agents can be enrolled into this policy by the user. - [x] The install & enroll commands should print an error to the console if the enroll command fails (due to being a managed policy or any other reason) #### So how do you associate an agent with a managed policy? Enroll in an unmanaged policy then set that policy to managed. We don't restrict the agent policy, only what other things (agents, integrations) can do if they're associated with a managed policy. A _force flag_ has been mentioned for some other actions. It might work here as well, but I'd like to handle discussion & implementation of those later. ### Manual testing <details><summary>Prevent enroll for managed policies</summary> 1. Created a managed agent policy ``` curl --user elastic:changeme -X POST localhost:5601/api/fleet/agent_policies -H 'Content-Type: application/json' -d'{ "name": "User created MANAGED", "namespace": "default", "is_managed": true}' -H 'kbn-xsrf: true' {"item":{"id":"3bd07db0-67d0-11eb-b656-21ad68ebfa8a","name":"User created MANAGED","namespace":"default","is_managed":true,"revision":1,"updated_at":"2021-02-05T16:36:01.931Z","updated_by":"elastic"}} ``` 2. Try `install` command show in the UI ``` sudo ./elastic-agent install -f --kibana-url=http://localhost:5601 --enrollment-token=WmcwTWMzY0IzWlBUUWJJUjZqRDA6UGRZelVlaS1STml1cVdjSUVwSkJRQQ== --insecure Password: The Elastic Agent is currently in BETA and should not be used in production Error: fail to enroll: fail to execute request to Kibana: Status code: 400, Kibana returned an error: Bad Request, message: Cannot enroll in managed policy 3bd07db0-67d0-11eb-b656-21ad68ebfa8a Error: enroll command failed with exit code: 1 ``` 3. Observe `Cannot enroll in managed policy 3bd07db0-67d0-11eb-b656-21ad68ebfa8a` error 4. Try `enroll` instead: ``` sudo ./elastic-agent enroll http://localhost:5601 WmcwTWMzY0IzWlBUUWJJUjZqRDA6UGRZelVlaS1STml1cVdjSUVwSkJRQQ== --insecure The Elastic Agent is currently in BETA and should not be used in production This will replace your current settings. Do you want to continue? [Y/n]: Error: fail to enroll: fail to execute request to Kibana: Status code: 400, Kibana returned an error: Bad Request, message: Cannot enroll in managed policy 3bd07db0-67d0-11eb-b656-21ad68ebfa8a ``` 5. Observe same `Cannot enroll in managed policy 3bd07db0-67d0-11eb-b656-21ad68ebfa8a` error </details> <details><summary>Enroll in unmanaged policy, then update it to managed</summary> Agent policies are `is_managed: false` by default, or we can update the policy to `is_managed: false`, like: ``` curl --user elastic:changeme -X PUT localhost:5601/api/fleet/agent_policies/3bd07db0-67d0-11eb-b656-21ad68ebfa8a -H 'Content-Type: application/json' -d'{ "is_managed": false, "name": "xyz", "namespace": "default" }' -H 'kbn-xsrf: true' {"item":{"id":"3bd07db0-67d0-11eb-b656-21ad68ebfa8a","name":"xyz","namespace":"default","is_managed":false,"revision":4,"updated_at":"2021-02-05T17:42:05.610Z","updated_by":"elastic","package_policies":[]}} ``` then enroll ``` sudo ./elastic-agent install -f --kibana-url=http://localhost:5601 --enrollment-token=WmcwTWMzY0IzWlBUUWJJUjZqRDA6UGRZelVlaS1STml1cVdjSUVwSkJRQQ== --insecure The Elastic Agent is currently in BETA and should not be used in production Successfully enrolled the Elastic Agent. Installation was successful and Elastic Agent is running. ``` and set the policy back to managed ``` curl --user elastic:changeme -X PUT localhost:5601/api/fleet/agent_policies/3bd07db0-67d0-11eb-b656-21ad68ebfa8a -H 'Content-Type: application/json' -d'{ "is_managed": true, "name": "xyz", "namespace": "default" }' -H 'kbn-xsrf: true' {"item":{"id":"3bd07db0-67d0-11eb-b656-21ad68ebfa8a","name":"xyz","namespace":"default","is_managed":true,"revision":5,"updated_at":"2021-02-05T17:44:18.757Z","updated_by":"elastic","package_policies":[]}} ``` with all the restrictions that entails (cannot unenroll, reassign, etc) ``` curl --user elastic:changeme -X PUT 'http://localhost:5601/api/fleet/agents/8169f0a0-67d9-11eb-80f2-73dd45e7318e/reassign' -X 'PUT' -H 'kbn-xsrf: abc' -H 'Content-Type: application/json' --data-raw '{"policy_id":"729f8440-67cf-11eb-b656-21ad68ebfa8a"}' { "statusCode": 400, "error": "Bad Request", "message": "Cannot reassign an agent from managed agent policy 3bd07db0-67d0-11eb-b656-21ad68ebfa8a" } ``` </details> ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
731e333078
commit
810e4ab8e8
|
@ -11,11 +11,13 @@ import semverParse from 'semver/functions/parse';
|
|||
import semverDiff from 'semver/functions/diff';
|
||||
import semverLte from 'semver/functions/lte';
|
||||
|
||||
import { SavedObjectsClientContract } from 'src/core/server';
|
||||
import { AgentType, Agent, AgentSOAttributes, FleetServerAgent } from '../../types';
|
||||
import type { SavedObjectsClientContract } from 'src/core/server';
|
||||
import type { AgentType, Agent, AgentSOAttributes, FleetServerAgent } from '../../types';
|
||||
import { savedObjectToAgent } from './saved_objects';
|
||||
import { AGENT_SAVED_OBJECT_TYPE, AGENTS_INDEX } from '../../constants';
|
||||
import { IngestManagerError } from '../../errors';
|
||||
import * as APIKeyService from '../api_keys';
|
||||
import { agentPolicyService } from '../../services';
|
||||
import { appContextService } from '../app_context';
|
||||
|
||||
export async function enroll(
|
||||
|
@ -27,6 +29,11 @@ export async function enroll(
|
|||
const agentVersion = metadata?.local?.elastic?.agent?.version;
|
||||
validateAgentVersion(agentVersion);
|
||||
|
||||
const agentPolicy = await agentPolicyService.get(soClient, agentPolicyId, false);
|
||||
if (agentPolicy?.is_managed) {
|
||||
throw new IngestManagerError(`Cannot enroll in managed policy ${agentPolicyId}`);
|
||||
}
|
||||
|
||||
if (appContextService.getConfig()?.agents?.fleetServerEnabled) {
|
||||
const esClient = appContextService.getInternalUserESClient();
|
||||
|
||||
|
|
|
@ -18,8 +18,9 @@ export default function (providerContext: FtrProviderContext) {
|
|||
const esArchiver = getService('esArchiver');
|
||||
const esClient = getService('es');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
|
||||
const supertestWithAuth = getService('supertest');
|
||||
const supertest = getSupertestWithoutAuth(providerContext);
|
||||
|
||||
let apiKey: { id: string; api_key: string };
|
||||
let kibanaVersion: string;
|
||||
|
||||
|
@ -58,6 +59,51 @@ export default function (providerContext: FtrProviderContext) {
|
|||
await esArchiver.unload('fleet/agents');
|
||||
});
|
||||
|
||||
it('should not allow enrolling in a managed policy', async () => {
|
||||
// update existing policy to managed
|
||||
await supertestWithAuth
|
||||
.put(`/api/fleet/agent_policies/policy1`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({
|
||||
name: 'Test policy',
|
||||
namespace: 'default',
|
||||
is_managed: true,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
// try to enroll in managed policy
|
||||
const { body } = await supertest
|
||||
.post(`/api/fleet/agents/enroll`)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.set(
|
||||
'Authorization',
|
||||
`ApiKey ${Buffer.from(`${apiKey.id}:${apiKey.api_key}`).toString('base64')}`
|
||||
)
|
||||
.send({
|
||||
type: 'PERMANENT',
|
||||
metadata: {
|
||||
local: {
|
||||
elastic: { agent: { version: kibanaVersion } },
|
||||
},
|
||||
user_provided: {},
|
||||
},
|
||||
})
|
||||
.expect(400);
|
||||
|
||||
expect(body.message).to.contain('Cannot enroll in managed policy');
|
||||
|
||||
// restore to original (unmanaged)
|
||||
await supertestWithAuth
|
||||
.put(`/api/fleet/agent_policies/policy1`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({
|
||||
name: 'Test policy',
|
||||
namespace: 'default',
|
||||
is_managed: false,
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('should not allow to enroll an agent with a invalid enrollment', async () => {
|
||||
await supertest
|
||||
.post(`/api/fleet/agents/enroll`)
|
||||
|
|
Loading…
Reference in a new issue