Unable to create url using generated API Key

Hello :slight_smile:

I'm trying to generate a short url using the REST api, and trying to authenticate using an API key i've generated before, no matter which cluster roles or indices priviliges I specify in the API key generation, I keep getting the error -

{
    "statusCode": 403,
    "error": "Forbidden",
    "message": "Unable to create url"
}

I'm using Elastic 7.8.1.

How I generated the API Key -

POST /_security/api_key
{
  "name": "kfir-url-shorten",
  "expiration": "1d", 
  "role_descriptors": { 
    "role-a": {
      "cluster": ["all"],
      "indices": [
        {
          "names": ["*"],
          "privileges": ["all"]
        }
      ]
    }
  }
}

My http request -

url = "<elastic cluter>:<port>/api/shorten_url"

payload = "{'url':'<some long url here>'}"
headers = {
    'Authorization': "ApiKey <my base64 api key>",
    'Content-Type': "application/json",
    'kbn-xsrf': "true"
    }

response = requests.request("POST", url, data=payload, headers=headers)

Not sure what other permissions I can give or even if this is possible using an API key..

Hope someone encountered this and can help me :pray:
thanks!

Hey @Kfir_Stri,

Welcome to the discussion boards!

The ability to create short urls is controlled by what we call "Kibana Privileges", as opposed to the cluster/index privileges that you may be accustomed to.

The good news is that we can adapt your API Key to grant this privilege. The bad news is that this has the potential to be fragile, and may not work on future versions of the stack. The API for creating API Keys is controlled by Elasticsearch, but the way that Kibana implements its privilege system is rather obtuse from that perspective.

Assuming you haven't changed Kibana's index (the kibana.index setting within kibana.yml), your API Key should look something like this:

POST /_security/api_key
{
  "name": "kfir-url-shorten",
  "expiration": "1d",
  "role_descriptors": {
    "role-a": {
      "cluster": [],
      "indices": [],
      "applications": [
        {
          "application": "kibana-.kibana",
          "privileges": [
            "feature_discover.all"
          ],
          "resources": [
            "*"
          ]
        }
      ]
    }
  }
}

Now for some details:

The privileges field tells Kibana which privileges you want this API Key to have. There are several privileges which grant the ability to create short URLs - the Discover privilege is one of them. I picked that one arbitrarily, but we could also create one with the visualize or dashboard feature as well.

The resources field tells Kibana which spaces this privilege should apply to. I chose the * resource, which means that this API Key will be able to create short urls in every space. If you want to restrict this to a specific space, then you can do something like:

POST /_security/api_key
{
  "name": "kfir-url-shorten",
  "expiration": "1d",
  "role_descriptors": {
    "role-a": {
      "cluster": [],
      "indices": [],
      "applications": [
        {
          "application": "kibana-.kibana",
          "privileges": [
            "feature_discover.all"
          ],
          "resources": [
            "space:default"
          ]
        }
      ]
    }
  }
}

This will grant access to just the default space, and no other spaces.

For short urls, there isn't a need to grant any cluster or index privileges, so I've omitted them from this example. Feel free to add those privileges back in if you need them for another purpose.

I hope this has helped - let me know if that works for you, or if you have any other questions.

1 Like

Awesome, it works!
Thanks for the explanation @Larry_Gregory :slight_smile:

I just checked out GET /_security/privilege and can see the whole possible privileges and how to use them, makes more sense now :+1:

How do I find out which other resources I have? or is this specified in the kibana.index file?

2 Likes

How do I find out which other resources I have? or is this specified in the kibana.index file?

The resources field is currently just used to denote which spaces the privilege should be applied to - so a query for the current set of spaces would tell you which other resources are available. Note that the resource name is space: followed by the space id as returned from the spaces API.

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