[Fleet] Cannot delete a managed agent policy (#90505)

## Summary
Managed policy cannot be deleted via API or UI

closes https://github.com/elastic/kibana/issues/90448

### 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

#### Manual testing
<details><summary>UI screenshot</summary>

<img width="1522" alt="Screen Shot 2021-02-05 at 1 56 13 PM" src="https://user-images.githubusercontent.com/57655/107076955-2ce95800-67ba-11eb-8bd4-d2ba3182e516.png">

</details>

<details><summary>API commands</summary>

```
## Create a managed 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":"17ebd160-67ee-11eb-adb2-f16c6e20580c","name":"User created MANAGED","namespace":"default","is_managed":true,"revision":1,"updated_at":"2021-02-05T20:09:46.614Z","updated_by":"elastic"}}

## Cannot delete it
curl --user elastic:changeme -X POST 'http://localhost:5601/api/fleet/agent_policies/delete'   -H 'kbn-xsrf: abc'  -H 'Content-Type: application/json'   --data-raw '{"agentPolicyId": "17ebd160-67ee-11eb-adb2-f16c6e20580c" }'    
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Cannot delete managed policy 17ebd160-67ee-11eb-adb2-f16c6e20580c"
}

## Set policy to unmanaged
curl --user elastic:changeme -X PUT localhost:5601/api/fleet/agent_policies/17ebd160-67ee-11eb-adb2-f16c6e20580c -H 'Content-Type: application/json' -d'{ "name": "User created MANAGED", "namespace": "default", "is_managed": false}' -H 'kbn-xsrf: true' 
{
  "item": {
    "id": "17ebd160-67ee-11eb-adb2-f16c6e20580c",
    "name": "User created MANAGED",
    "namespace": "default",
    "is_managed": false,
    "revision": 3,
    "updated_at": "2021-02-05T20:10:45.383Z",
    "updated_by": "elastic",
    "package_policies": []
  }
}

## Can delete
curl --user elastic:changeme -X POST 'http://localhost:5601/api/fleet/agent_policies/delete'   -H 'kbn-xsrf: abc'  -H 'Content-Type: application/json'   --data-raw '{"agentPolicyId": "17ebd160-67ee-11eb-adb2-f16c6e20580c" }'    
{
  "id": "17ebd160-67ee-11eb-adb2-f16c6e20580c",
  "name": "User created MANAGED"
}


```
</details>
This commit is contained in:
John Schulz 2021-02-08 12:13:55 -05:00 committed by GitHub
parent ec672f5df2
commit bda7b2816f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 93 additions and 7 deletions

View file

@ -34,3 +34,4 @@ export class FleetAdminUserInvalidError extends IngestManagerError {}
export class ConcurrentInstallOperationError extends IngestManagerError {}
export class AgentReassignmentError extends IngestManagerError {}
export class AgentUnenrollmentError extends IngestManagerError {}
export class AgentPolicyDeletionError extends IngestManagerError {}

View file

@ -36,7 +36,7 @@ import {
FleetServerPolicy,
AGENT_POLICY_INDEX,
} from '../../common';
import { AgentPolicyNameExistsError } from '../errors';
import { AgentPolicyNameExistsError, AgentPolicyDeletionError } from '../errors';
import { createAgentPolicyAction, listAgents } from './agents';
import { packagePolicyService } from './package_policy';
import { outputService } from './output';
@ -448,6 +448,10 @@ class AgentPolicyService {
throw new Error('Agent policy not found');
}
if (agentPolicy.is_managed) {
throw new AgentPolicyDeletionError(`Cannot delete managed policy ${id}`);
}
const {
defaultAgentPolicy: { id: defaultAgentPolicyId },
} = await this.ensureDefaultAgentPolicy(soClient, esClient);

View file

@ -38,9 +38,8 @@ export default function ({ getService }: FtrProviderContext) {
})
.expect(200);
const getRes = await supertest.get(`/api/fleet/agent_policies/${createdPolicy.id}`);
const json = getRes.body;
expect(json.item.is_managed).to.equal(false);
const { body } = await supertest.get(`/api/fleet/agent_policies/${createdPolicy.id}`);
expect(body.item.is_managed).to.equal(false);
});
it('sets given is_managed value', async () => {
@ -56,9 +55,25 @@ export default function ({ getService }: FtrProviderContext) {
})
.expect(200);
const getRes = await supertest.get(`/api/fleet/agent_policies/${createdPolicy.id}`);
const json = getRes.body;
expect(json.item.is_managed).to.equal(true);
const { body } = await supertest.get(`/api/fleet/agent_policies/${createdPolicy.id}`);
expect(body.item.is_managed).to.equal(true);
const {
body: { item: createdPolicy2 },
} = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'TEST3',
namespace: 'default',
is_managed: false,
})
.expect(200);
const {
body: { item: policy2 },
} = await supertest.get(`/api/fleet/agent_policies/${createdPolicy2.id}`);
expect(policy2.is_managed).to.equal(false);
});
it('should return a 400 with an empty namespace', async () => {
@ -242,6 +257,23 @@ export default function ({ getService }: FtrProviderContext) {
const getRes = await supertest.get(`/api/fleet/agent_policies/${createdPolicy.id}`);
const json = getRes.body;
expect(json.item.is_managed).to.equal(true);
const {
body: { item: createdPolicy2 },
} = await supertest
.put(`/api/fleet/agent_policies/${agentPolicyId}`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'TEST2',
namespace: 'default',
is_managed: false,
})
.expect(200);
const {
body: { item: policy2 },
} = await supertest.get(`/api/fleet/agent_policies/${createdPolicy2.id}`);
expect(policy2.is_managed).to.equal(false);
});
it('should return a 409 if policy already exists with name given', async () => {
@ -276,5 +308,54 @@ export default function ({ getService }: FtrProviderContext) {
expect(body.message).to.match(/already exists?/);
});
});
describe('POST /api/fleet/agent_policies/delete', () => {
let managedPolicy: any | undefined;
it('should prevent managed policies being deleted', async () => {
const {
body: { item: createdPolicy },
} = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Managed policy',
namespace: 'default',
is_managed: true,
})
.expect(200);
managedPolicy = createdPolicy;
const { body } = await supertest
.post('/api/fleet/agent_policies/delete')
.set('kbn-xsrf', 'xxx')
.send({ agentPolicyId: managedPolicy.id })
.expect(400);
expect(body.message).to.contain('Cannot delete managed policy');
});
it('should allow unmanaged policies being deleted', async () => {
const {
body: { item: unmanagedPolicy },
} = await supertest
.put(`/api/fleet/agent_policies/${managedPolicy.id}`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Unmanaged policy',
namespace: 'default',
is_managed: false,
})
.expect(200);
const { body } = await supertest
.post('/api/fleet/agent_policies/delete')
.set('kbn-xsrf', 'xxx')
.send({ agentPolicyId: unmanagedPolicy.id });
expect(body).to.eql({
id: unmanagedPolicy.id,
name: 'Unmanaged policy',
});
});
});
});
}