[APM] Fix throwing appropriate error when user is missing necessary permission (#162466)

Closes https://github.com/elastic/kibana/issues/126078

Currently the 2 places where the user can create Agent Key already
handles the situation by not displaying the option to user with limited
permissions.

1. Observability - Settings
2. Stack Management -> API Keys

[Public
API](https://www.elastic.co/guide/en/kibana/current/agent-key-api.html)
is still available to create Agent Keys.

With this change the below would happen

### Request
```
curl -X POST "http://localhost:5601/{basePath}/api/apm/agent_keys" \
     -u editor:changeme \
     -H "Content-Type: application/json" \
     -H "Elastic-Api-Version: 2023-10-31" \
     -H "kbn-xsrf: true" \
     -d '{
        "name": "apm-key",
        "privileges": ["event:write", "config_agent:read"]
     }'
```
### Response
```
{
  "statusCode": 403,
  "error": "Forbidden",
  "message": "editor is missing the following requested privilege(s): config_agent:read, event:write and following cluster privileges - manage_api_key, manage_own_api_key privilege(s).    You might try with the superuser, or add the missing APM application privileges to the role of the authenticated user, eg.:\n    PUT /_security/role/my_role\n    {\n      ...\n      \"applications\": [{\n        \"application\": \"apm\",\n        \"privileges\": [\"config_agent:read\",\"event:write\"],\n        \"resources\": [*]\n      }],\n      ...\n    }",
  "attributes": {
    "data": {
      "missingPrivileges": [
        "config_agent:read",
        "event:write"
      ],
      "missingClusterPrivileges": [
        "manage_api_key",
        "manage_own_api_key"
      ]
    },
    "_inspect": [
      
    ]
  }
}
```
This commit is contained in:
Achyut Jhunjhunwala 2023-07-31 17:01:23 +02:00 committed by GitHub
parent 832aec0a8e
commit 5369eb32ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 5 deletions

View file

@ -12,6 +12,10 @@ export enum PrivilegeType {
AGENT_CONFIG = 'config_agent:read',
}
export enum ClusterPrivilegeType {
MANAGE_OWN_API_KEY = 'manage_own_api_key',
}
export const privilegesTypeRt = t.array(
t.union([
t.literal(PrivilegeType.EVENT),

View file

@ -8,8 +8,10 @@
import { SecurityCreateApiKeyResponse } from '@elastic/elasticsearch/lib/api/types';
import Boom from '@hapi/boom';
import { ApmPluginRequestHandlerContext } from '../typings';
import { ClusterPrivilegeType } from '../../../common/privilege_type';
const resource = '*';
const CLUSTER_PRIVILEGES = [ClusterPrivilegeType.MANAGE_OWN_API_KEY];
export interface CreateAgentKeyResponse {
agentKey: SecurityCreateApiKeyResponse;
@ -39,10 +41,12 @@ export async function createAgentKey({
application: userApplicationPrivileges,
username,
has_all_requested: hasRequiredPrivileges,
cluster: clusterPrivileges,
} = await coreContext.elasticsearch.client.asCurrentUser.security.hasPrivileges(
{
body: {
application: [application],
cluster: CLUSTER_PRIVILEGES,
},
}
);
@ -54,9 +58,19 @@ export async function createAgentKey({
.filter((x) => !x[1])
.map((x) => x[0]);
const missingClusterPrivileges = Object.keys(clusterPrivileges).filter(
(key) => !clusterPrivileges[key]
);
const error = `${username} is missing the following requested privilege(s): ${missingPrivileges.join(
', '
)}.\
)}${
missingClusterPrivileges && missingClusterPrivileges.length > 0
? ` and following cluster privileges - ${missingClusterPrivileges.join(
', '
)} privilege(s)`
: ''
}.\
You might try with the superuser, or add the missing APM application privileges to the role of the authenticated user, eg.:
PUT /_security/role/my_role
{
@ -68,7 +82,10 @@ export async function createAgentKey({
}],
...
}`;
throw Boom.internal(error, { missingPrivileges }, 403);
throw Boom.forbidden(error, {
missingPrivileges,
missingClusterPrivileges,
});
}
const body = {

View file

@ -5,7 +5,10 @@
* 2.0.
*/
import { PrivilegeType } from '../../../common/privilege_type';
import {
PrivilegeType,
ClusterPrivilegeType,
} from '../../../common/privilege_type';
export enum ApmUsername {
noAccessUser = 'no_access_user',
@ -67,7 +70,7 @@ export const customRoles = {
},
[ApmCustomRolename.apmManageOwnAgentKeys]: {
elasticsearch: {
cluster: ['manage_own_api_key'],
cluster: [ClusterPrivilegeType.MANAGE_OWN_API_KEY],
},
},
[ApmCustomRolename.apmManageOwnAndCreateAgentKeys]: {

View file

@ -6,7 +6,7 @@
*/
import expect from '@kbn/expect';
import { first } from 'lodash';
import { PrivilegeType } from '@kbn/apm-plugin/common/privilege_type';
import { PrivilegeType, ClusterPrivilegeType } from '@kbn/apm-plugin/common/privilege_type';
import { ApmUsername } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/authentication';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { ApmApiError, ApmApiSupertest } from '../../../common/apm_api_supertest';
@ -19,6 +19,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const agentKeyName = 'test';
const allApplicationPrivileges = [PrivilegeType.AGENT_CONFIG, PrivilegeType.EVENT];
const clusterPrivileges = [ClusterPrivilegeType.MANAGE_OWN_API_KEY];
async function createAgentKey(apiClient: ApmApiSupertest, privileges = allApplicationPrivileges) {
return await apiClient({
@ -60,6 +61,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
_inspect: [],
data: {
missingPrivileges: allApplicationPrivileges,
missingClusterPrivileges: clusterPrivileges,
},
});
});