# APM ApiKey Failing with Unauthorized (Wrong permissions documented?)

**URL:** https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663
**Category:** APM
**Tags:** docker, go, server
**Created:** [July 2, 2021, 3:23pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663 "2021-07-02T15:23:26Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 2, 2021, 3:23pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/1 "2021-07-02T15:23:26Z")

</div>

**Kibana version** :  
7.13.2

**Elasticsearch version** :  
7.13.2

**APM Server version** :  
7.13.2

**APM Agent language and version** :  
N/A

**Browser version** :  
N/A

**Original install method (e.g. download page, yum, deb, from source, etc.) and version**:  
ECK (1.6.0)

**Fresh install or upgraded from other version?**  
Fresh Install

**Is there anything special in your setup?**  
No

**Description of the problem including expected versus actual behavior. Please include screenshots (if relevant)**:  
When trying to create and test an API key to use for APM, I consistently get an unauthorized error.

**Steps to reproduce** :

1. Deploy APM server via ECK:

```auto
---
apiVersion: apm.k8s.elastic.co/v1
kind: ApmServer
metadata:
  name: apm-prod
  namespace: apm-prod
spec:
  version: 7.13.2
  count: 1
  elasticsearchRef:
    name: es-prod
    namespace: elastic-prod
  kibanaRef:
    name: kibana-prod
    namespace: kibana-prod
  http:
    tls:
      certificate:
        secretName: apm-cert
  config:
    apm-server:
      auth:
        api_key:
          enabled: true
          limit: 100
      capture_personal_data: true # TODO check if we want this enabled
      # TODO RUM?
      kibana:
        enabled: true
        ssl.enabled: true
        ssl.verification_mode: certificate
        ssl.certificate_authorities: ["/usr/share/apm-server/certs/<snipped>"]
    output:
      elasticsearch:
        ssl.enabled: true
        ssl.certificate_authorities: ["/usr/share/apm-server/certs/<snipped>"]
        ssl.verification_mode: certificate
    http:
      enabled: true
      host: 0.0.0.0
      port: 5067
    monitoring:
      enabled: false
      cluster_uuid: "<snipped>"
  podTemplate:
    metadata:
      annotations:
        linkerd.io/inject: enabled
        config.linkerd.io/proxy-cpu-limit: "2"
        co.elastic.metrics/raw: '[{"enabled":true,"module":"beat","hosts":["http://${data.host}:5067"],"metricsets":["stats","state"],"period":"10s","timeout":"3s","xpack":{"enabled":true}}]'
    spec:
      automountServiceAccountToken: true
      containers:
        - name: apm-server
          resources:
            limits:
              memory: 2Gi
              cpu: 2
          volumeMounts:
            - name: <snipped>
              mountPath: /usr/share/apm-server/certs
      volumes:
        - name: <snipped>
          secret:
            secretName: <snipped>
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    elasticsearch.k8s.elastic.co/cluster-name: es-prod
                topologyKey: kubernetes.io/hostname

```

1. APM Server connects successfully to both Kibana and Elasticsearch:

```json
{"log.level":"info","@timestamp":"2021-07-02T14:55:07.998Z","log.logger":"kibana","log.origin":{"file.name":"kibana/connecting_client.go","file.line":83},"message":"Successfully obtained connection to Kibana.","ecs.version":"1.6.0"}

```

```json
{"log.level":"debug","@timestamp":"2021-07-02T14:55:07.968Z","log.logger":"esclientleg","log.origin":{"file.name":"eslegclient/connection.go","file.line":364},"message":"GET https://es-prod-es-http.elastic-prod.svc:9200/_xpack <nil>","ecs.version":"1.6.0"}

```

1. Create APM Agent API key based off of [guide](https://www.elastic.co/guide/en/apm/server/7.13/api-key.html#create-api-key-workflow-es).

```json
POST /_security/api_key
{
  "name": "go-agent",
  "role_descriptors": {
    "apm": {
      "applications": [
        {
          "application": "apm",
          "privileges": ["sourcemap:write", "event:write", "config_agent:read"],
          "resources": ["*"]
        }
      ]
    }
  }
}

```

1. Base64 encode API ID:Key

```auto
echo -n '<ID>:<Key>' | base64

```

1. Test API Key:

```auto
curl -X GET -H "Authorization: ApiKey <base64_encoded_apiKey>" https://<apm_server_url>:8200/intake/v2/events

```

1. Get error:

```auto
{
  "error": "unauthorized"
}

```

1. Error in APM server logs:

```auto
{"log.level":"error","@timestamp":"2021-07-02T15:19:06.993Z","log.logger":"request","log.origin":{"file.name":"middleware/log_middleware.go","file.line":60},"message":"unauthorized","url.original":"/intake/v2/events","http.request.method":"GET","user_agent.original":"curl/7.66.0","source.address":"127.0.0.1","http.request.body.bytes":0,"http.request.id":"babb3ec6-acf8-4c11-96c3-4b348b7a087c","event.duration":138858,"http.response.status_code":401,"error.message":"unauthorized","ecs.version":"1.6.0"}

```

* * *

* * *

**Side note** : attempting to run the documented command:

```auto
curl -H "Authorization: ApiKey <base64_encoded_apiKey>" https://<elasticsearch_server_url>:9200/_security/_authentication

```

Results in the following error:

```auto
{"error":"Incorrect HTTP method for uri [/_security/_authentication] and method [GET], allowed: [POST]","status":405}

```

Attempting to use POST

```auto
curl -X POST -H "Authorization: ApiKey <base64_encoded_apiKey>" https://<elasticsearch_server_url>:9200/_security/_authentication

```

Results in error:

```auto
{"error":{"root_cause":[{"type":"parse_exception","reason":"request body is required"}],"type":"parse_exception","reason":"request body is required"},"status":400}

```

---

<div class="post-metadata">

### Author: ![axw](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/axw/32/28197_2.png) [@axw](https://discuss.elastic.co/u/axw)
#### Post date: [July 5, 2021, 2:01am UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/2 "2021-07-05T02:01:30Z")

</div>

> [@BenB196](#):
>
> **Side note** : attempting to run the documented command:

Sorry, there's a typo in the docs. I've opened [docs: fix typo by axw · Pull Request #5600 · elastic/apm-server · GitHub](https://github.com/elastic/apm-server/pull/5600) to fix that. The correct URL path is `/_security/_authenticate`.

Aside from that, I'm not sure where things are going wrong for you. I'll show what worked for me just now.

Create the API Key:

```auto
POST /_security/api_key
{
  "name": "go-agent",
  "role_descriptors": {
    "apm": {
      "applications": [
        {
          "application": "apm",
          "privileges": ["sourcemap:write", "event:write", "config_agent:read"],
          "resources": ["*"]
        }
      ]
    }
  }
}

```

Elasticsearch response:

```auto
{
  "id" : "GyZWdHoBbmV-n6Ll1ET0",
  "name" : "go-agent",
  "api_key" : "asEpXFz7Qza3zW9zkVBkaA"
}

```

Encode credentials:

```auto
$ echo -n 'GyZWdHoBbmV-n6Ll1ET0:asEpXFz7Qza3zW9zkVBkaA' | base64
R3laV2RIb0JibVYtbjZMbDFFVDA6YXNFcFhGejdRemEzelc5emtWQmthQQ==

```

Test credentials with Elasticsearch:

```auto
$ curl -H "Authorization: ApiKey R3laV2RIb0JibVYtbjZMbDFFVDA6YXNFcFhGejdRemEzelc5emtWQmthQQ==" http://localhost:9200/_security/_authenticate
{"username":"admin","roles":[],"full_name":null,"email":null,"metadata":{},"enabled":true,"authentication_realm":{"name":"_es_api_key","type":"_es_api_key"},"lookup_realm":{"name":"_es_api_key","type":"_es_api_key"},"authentication_type":"api_key"}

```

Test credentials with APM Server:

```auto
$ curl -H "Authorization: ApiKey R3laV2RIb0JibVYtbjZMbDFFVDA6YXNFcFhGejdRemEzelc5emtWQmthQQ==" http://localhost:8200/intake/v2/events
{                                                  
  "accepted": 0,                                   
  "errors": [                                      
    {                                              
      "message": "only POST requests are supported"
    }                                              
  ]                                                
}                                                  

```

(That error is expected, and will only be returned if the API Key is verified.)

---

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 5, 2021, 2:19pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/3 "2021-07-05T14:19:17Z")

</div>

@axw Thanks for the updated command, after running the new command:

```auto
curl -H "Authorization: ApiKey <base64_encoded_apiKey>" https://<elasticsearch_server_url>:9200/_security/_authenticate

```

I get:

```json
{"username":"<username>","roles":[],"full_name":null,"email":null,"metadata":{"saml_nameid_format":"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified","saml_nameid":"<saml_username>","saml(groups)":[<saml_groups>]},"enabled":true,"authentication_realm":{"name":"_es_api_key","type":"_es_api_key"},"lookup_realm":{"name":"_es_api_key","type":"_es_api_key"},"authentication_type":"api_key"}

```

However, I'm still getting an unauthorized error when running:

```auto
curl -k -H "Authorization: ApiKey <base64_encoded_apiKey>" https://<apm_server_url>:8200/intake/v2/events

```

```auto
{
  "error": "unauthorized"
}

```

---

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 5, 2021, 2:49pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/4 "2021-07-05T14:49:51Z")

</div>

@axw I believe I found the issue, when I tried to generate the token via the apm-server itself:

```auto
apm-server -c config/config-secret/apm-server.yml apikey create --ingest --agent-config --name go-app

```

I got the following error:

```auto
apm-prod-apm-prod-apm-user is missing the following requested privilege(s): event:write, config_agent:read.

You might try with the superuser, or add the APM application privileges to the role of the authenticated user, eg.:
PUT /_security/role/my_role {
        ...
        "applications": [{
          "application": "apm",
          "privileges": ["sourcemap:write", "event:write", "config_agent:read"],
          "resources": ["*"]
        }],
        ...
}

```

It looks like the user that was generated by ECK for this deployment doesn't have the correct permissions.

I'm not sure if this is an issue with ECK or with APM, would you have any more insight into this?

---

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 5, 2021, 3:00pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/5 "2021-07-05T15:00:56Z")

</div>

Looking into this a bit more, it looks like ECK adds the user to the Elasticsearch deployment with the following roles:

```auto
eck_apm_user_role_v75,ingest_admin,apm_system

```

Not sure if these roles cover everything.

But one thing I did notice, is that if I try to get the user:

```auto
GET /_security/user/apm-prod-apm-prod-apm-user

```

I get a 404:

```auto
{ }

```

Not sure if this is intended, or if ECK never properly added the APM user to the cluster.

---

<div class="post-metadata">

### Author: ![axw](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/axw/32/28197_2.png) [@axw](https://discuss.elastic.co/u/axw)
#### Post date: [July 7, 2021, 3:43am UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/6 "2021-07-07T03:43:34Z")

</div>

> It looks like the user that was generated by ECK for this deployment doesn't have the correct permissions.

Right, the built-in `apm_user` role does not have sufficient privileges for creating API Keys. This is by design, to keep the privileges minimal.

The simplest way to create an API Key would be to use the `elastic` superuser. I think in your case, the secret would be `elastic-prod-elastic-user`. Alternatively, you can follow [Grant privileges and roles needed for API key management | APM User Guide [8.11] | Elastic](https://www.elastic.co/guide/en/apm/server/current/privileges-api-key.html) to create a more targeted role for creating the API Keys.

FYI we will be introducing a UI to manage of APM agent API Keys in the future, which I expect will simplify this: [[APM] Agent API Key Management · Issue #77966 · elastic/kibana · GitHub](https://github.com/elastic/kibana/issues/77966)

---

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 7, 2021, 5:40pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/7 "2021-07-07T17:40:40Z")

</div>

@axw so I did some more testing, but am still seeing an issue:

I created a new API Key specifically for the APM Server via (using the elastic superadmin account), and deployed it to the APM Server:

```json
POST /_security/api_key
{
  "name": "apm_server_api_key",
  "role_descriptors": {
    "apm_setup": {
      "cluster": [
        "manage_ilm", "manage_index_templates", "manage_pipeline"
      ],
      "index": [
        {
          "names": ["apm-*"],
          "privileges": ["manage"]
        }
      ]
    },
    "apm_writer": {
      "index": [
        {
          "names": ["apm-*"],
          "privileges": ["create_doc","create_index"]
        },
        {
          "names": ["apm-*sourcemap"],
          "privileges": ["read"]
        }
      ]
    },
    "apm_system": {
      "cluster": ["monitor","cluster:admin/xpack/monitoring/bulk"],
      "index": [
        {
          "names": [".monitoring-beats-*"],
          "privileges": ["create_index","create_doc"]
        }
      ]
    },
    "apm_manage_api_key": {
      "cluster": [
        "manage_api_key"
      ],
      "applications": [
        {
          "application": "apm",
          "privileges": ["sourcemap:write", "event:write", "config_agent:read"],
          "resources": ["*"]
        }
      ]
    }
  }
}

```

The APM server appears to startup and connect to Elasticsearch and Kibana perfectly fine.

However, when I run:

```auto
apm-server -c config/config-secret/apm-server.yml apikey create --ingest --agent-config --name go-app

```

I am seeing the error:

```auto
"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"creating derived api keys requires an explicit role descriptor that is empty (has no privileges)"}],"type":"illegal_argument_exception","reason":"creating derived api keys requires an explicit role descriptor that is empty (has no privileges)"},"status":400}

```

---

<div class="post-metadata">

### Author: ![axw](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/axw/32/28197_2.png) [@axw](https://discuss.elastic.co/u/axw)
#### Post date: [July 8, 2021, 3:09am UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/8 "2021-07-08T03:09:53Z")

</div>

Per [Create API key API | Elasticsearch Guide [7.13] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html), you cannot use an API Key to create another API Key except if the target API Key is to have no privileges. So I'm afraid that this approach isn't going to work. You would have to instead create a user for apm-server with those roles, and set up apm-server with user/password basic auth.

---

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 8, 2021, 1:46pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/9 "2021-07-08T13:46:50Z")

</div>

@axw thanks I completely missed that part.

I've created a new user with the following:

```auto
{
  "apm_server" : {
    "username" : "apm_server",
    "roles" : [
      "apm_system",
      "ingest_admin",
      "apm_manage_api_key",
      "apm_setup",
      "apm_writer"
    ],
    "full_name" : "",
    "email" : "",
    "metadata" : { },
    "enabled" : true
  }
}

```

apm\_manage\_api\_key role:

```auto
{
  "apm_manage_api_key" : {
    "cluster" : [
      "manage_api_key"
    ],
    "indices" : [],
    "applications" : [
      {
        "application" : "apm",
        "privileges" : [
          "sourcemap:write",
          "event:write",
          "config_agent:read"
        ],
        "resources" : [
          "*"
        ]
      }
    ],
    "run_as" : [],
    "metadata" : { },
    "transient_metadata" : {
      "enabled" : true
    }
  }
}

```

apm\_setup role:

```auto
{
  "apm_setup" : {
    "cluster" : [
      "manage_ilm",
      "manage_index_templates",
      "manage_pipeline"
    ],
    "indices" : [
      {
        "names" : [
          "apm-*"
        ],
        "privileges" : [
          "manage"
        ],
        "field_security" : {
          "grant" : [
            "*"
          ],
          "except" : []
        },
        "allow_restricted_indices" : false
      }
    ],
    "applications" : [],
    "run_as" : [],
    "metadata" : { },
    "transient_metadata" : {
      "enabled" : true
    }
  }
}

```

apm\_writer role:

```auto
{
  "apm_writer" : {
    "cluster" : [],
    "indices" : [
      {
        "names" : [
          "apm-*"
        ],
        "privileges" : [
          "create_doc",
          "create"
        ],
        "field_security" : {
          "grant" : [
            "*"
          ],
          "except" : []
        },
        "allow_restricted_indices" : false
      },
      {
        "names" : [
          "apm-*sourcemap"
        ],
        "privileges" : [
          "read"
        ],
        "field_security" : {
          "grant" : [
            "*"
          ]
        },
        "allow_restricted_indices" : false
      }
    ],
    "applications" : [],
    "run_as" : [],
    "metadata" : { },
    "transient_metadata" : {
      "enabled" : true
    }
  }
}

```

I then generated an API with the apm\_server user:

```auto
POST /_security/api_key
{
  "name": "go-agent",
  "role_descriptors": {
    "apm": {
      "applications": [
        {
          "application": "apm",
          "privileges": ["sourcemap:write", "event:write", "config_agent:read"],
          "resources": ["*"]
        }
      ]
    }
  }
}

```

If I run the API Key through the APM Server check everything passes:

```auto
apm-server -c config/config-secret/apm-server.yml apikey verify --credentials <base64_api_id:key>

```

```auto
Authorized for privilege "config_agent:read"...: Yes
Authorized for privilege "event:write"...: Yes
Authorized for privilege "sourcemap:write"...: Yes

```

And if I try the key directly against Elasticsearch via:

```auto
curl -H "Authorization: ApiKey <base64_api_id:key>" https://<elasticsearch_url>:9200/_security/_authenticate

```

I get:

```auto
{"username":"apm_server","roles":[],"full_name":"","email":"","metadata":{},"enabled":true,"authentication_realm":{"name":"_es_api_key","type":"_es_api_key"},"lookup_realm":{"name":"_es_api_key","type":"_es_api_key"},"authentication_type":"api_key"}

```

But when I try to execute the curl command against the APM server via:

```auto
curl --cacert /etc/pki/trust/anchors/<root_ca>.pem -H "Authorization: ApiKey <base64_api_id:key>" https://<apm_server_url>:8200/intake/v2/events

```

I am still getting an unauthorized:

```auto
{
  "error": "unauthorized"
}

```

---

<div class="post-metadata">

### Author: ![axw](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/axw/32/28197_2.png) [@axw](https://discuss.elastic.co/u/axw)
#### Post date: [July 9, 2021, 5:52am UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/10 "2021-07-09T05:52:49Z")

</div>

I overlooked something in your server config earlier:

```auto
apm-server:
  auth:
    api_key:
      enabled: true
      limit: 100

```

I guess you were referring to the `apm-server.yml` in github, on the master branch? There have been some recent changes that were not yet released in 7.13.2. Try changing this to:

```auto
apm-server:
  api_key:
    enabled: true
    limit: 100

```

We are reorganising some of the auth-related config under `apm-server.auth`, including `api_key` and `secret_token`. The old name for `apm-server.auth.api_key` config is `apm-server.api_key`.

---

<div class="post-metadata">

### Author: ![BenB196](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/benb196/32/83401_2.png) [@BenB196](https://discuss.elastic.co/u/BenB196)
#### Post date: [July 9, 2021, 12:31pm UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/11 "2021-07-09T12:31:57Z")

</div>

@axw yep, that was the issue. I wasn't able to find the default config on the docs page so went to GitHub, and didn't think about changing the branch.

Thanks for the help on this.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)
#### Post date: [July 30, 2021, 8:32am UTC](https://discuss.elastic.co/t/apm-apikey-failing-with-unauthorized-wrong-permissions-documented/277663/12 "2021-07-30T08:32:43Z")

</div>

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.
