401 Unathorized when trying to call the Kibana API

I am trying to use a generated API key to export my workpads. However no matter what i do i end up getting a 401 unathorized back from Kibana.

This happens even when i use the exact curl command from the documentation here.

curl --location --request GET 'https://kibana.mydomain.net:5601/api/security/role' \
--header 'Content-Type: application/json;charset=UTF-8' \
--header 'kbn-xsrf: true' \
--header 'Authorization: ApiKey <myApiKey>'

The user i created the API key with has the superuser role.

Do you have any proxies at play in your set up?

No proxies but i do use a Netscaler to do http load balancing across my 3 nodes.

Which version are you on? API key authentication for Kibana was added in 7.7

I am using 7.9.3 on both Kibana and Elasticsearch.

It may be that I am missing this part in my kibana.yml?

xpack.security.authc:
  providers: [basic]
  http:
    enabled: true
    autoSchemesEnabled: true
    schemes: [apikey]

@Larry_Gregory Maybe you can help us on that one?

You shouldn't have to change the configuration for xpack.security.authc.http.*, as the default behavior allows for API Keys. If you have changed it, then try removing any customizations for the time being.

Can you try to issue a curl command to Elasticsearch using that API Key? I want to eliminate ES before we dig into Kibana:

If that comes back with a 200 response, then here's what I'd like you to try next:

Enable Debug logging for Kibana's security features (restart after applying these changes)

# kibana.yml
logging:
  loggers:
    - context: core
      appenders: [console]
      level: debug
    - context: plugins.security
      appenders: [console]
      level: debug

Reissue the curl command, but with the -v flag to capture verbose output

If you can provide us with both the verbose curl output, and the debug logs that were captured, then we can try to narrow this down further.

Hi Larry, sorry for answering late. I tried running the curl command but I still get the following reply with my super user API key.

    root@55a670227580:/# curl -v --location --request GET 'https://elastic.mydomain.net:9200/_security/_authenticate' --header 'Authorization: ApiKey <removed>' -k
    Note: Unnecessary use of -X or --request, GET is already inferred.
    *   Trying 172.18.112.110:9200...
    * TCP_NODELAY set
    * Connected to elastic.mydomain.net (172.18.112.110) port 9200 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: /etc/ssl/certs/ca-certificates.crt
      CApath: /etc/ssl/certs
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA
    * ALPN, server accepted to use http/1.1
    * Server certificate:
    *  subject: C=DK; L=Copenhagen; O=mydomain A/S; CN=elastic.mydomain.net
    *  start date: Aug 11 13:08:00 2020 GMT
    *  expire date: Aug 11 13:08:00 2022 GMT
    *  issuer: DC=net; DC=mydomain; CN=mydomain Issuing CA 1
    *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    > GET /_security/_authenticate HTTP/1.1
    > Host: elastic.mydomain.net:9200
    > User-Agent: curl/7.68.0
    > Accept: */*
    > Authorization: ApiKey <removed>
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 401 Unauthorized
    < WWW-Authenticate: Basic realm="security" charset="UTF-8"
    < WWW-Authenticate: Bearer realm="security"
    < WWW-Authenticate: ApiKey
    < content-type: application/json; charset=UTF-8
    < content-length: 505
    <
    * Connection #0 to host elastic.mydomain.net left intact
    {"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/_security/_authenticate]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}}],"type":"security_exception","reason":"missing authentication credentials for REST request [/_security/_authenticate]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}},"status":401}

Thanks @rbjoergensen, this at least eliminates Kibana as the root cause of this problem. We've seen similar issues in the past when the API Key isn't encoded properly. Can you describe how you encoded the API Key?

Example

Here's an API Key that I created locally:

{
  "id" : "bf3_-HQBbk4H6L_-UFw6",
  "name" : "my_api_key",
  "api_key" : "zkwoTguIS469-nRvtL4LQA"
}

Then, I used this command to encode the API Key. This is the concatenation of the id and api_key fields, separated by a colon (:):

echo -n 'bf3_-HQBbk4H6L_-UFw6:zkwoTguIS469-nRvtL4LQA' | base64

NOTE the -n is important, as it prevents a newline character from being added. This newline character can cause your key to be incorrectly encoded.

Thank you Larry.

That helped me find the problem.
My encoder was using Unicode as a default instead of UTF8 encoding of the key.

Thanks for taking the time to help me out.

1 Like