Elasticsearch API key & PHP
1 min read

Elasticsearch API key & PHP

How to setup API key for Elasticsearch and use it with PHP

When you enable XPACK security in Elasticsearch, your clients (my website in this case) requires authentication to be setup. If you do not setup proper authentication, you will get similar errors.

Elastic\Elasticsearch\Exception\ClientResponseException
401 Unauthorized: 
{
	"error": {
		"root_cause": [
			{
				"type": "security_exception",
				"reason": "missing authentication credentials for REST request [/index/_search]",
				"header": { "WWW-Authenticate": ["Basic realm=\"security\" charset=\"UTF-8\"", "ApiKey"] }
			}
		],
		"type": "security_exception",
		"reason": "missing authentication credentials for REST request [/index/_search]",
		"header": { "WWW-Authenticate": ["Basic realm=\"security\" charset=\"UTF-8\"", "ApiKey"] }
	},
	"status": 401
}

I found two ways to solve this, I could setup either one of these:

  • basic authentication
  • API Key

Basic Authentication

Use this guide to generate an username / password combination, default username is elastic

Using Elastic Search client:

$client = ClientBuilder::create()
->setBasicAuthentication('<username>', '<password>')
->build();

If you use configuration files, you can set up the following key basicAuthentication in your node pool

'hosts' => [
	localhost:9200'
],
'basicAuthentication' => [
              '<username>',
              '<password>'          
]

Using babenkoivan/elastic-client

If you use babenkoivan/elastic-client (I use it for Laravel), publish the config file and go to elastic.client.php and add it under your connections

<?php declare(strict_types=1);

return [
    'default' => env('ELASTIC_CONNECTION', 'default'),
    'connections' => [
        'default' => [
            'hosts' => [
                env('SCOUT_ELASTIC_HOST', 'localhost:9200'),
            ],
           'basicAuthentication' => [
              '<username>',
              '<password>'          
			]
        ],
    ],
];

API Key

To generate an API key, you will still require the username & password from basic authentication. Then you can generate an API key first using either cURL or Kibana. I used this query:

curl --location --request POST 'http://<username>:<password>@localhost:9200/_security/api_key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "php-client"
}'

This returned a response with the api_key and id key

{
    "id": "<id>",
    "name": "php-client",
    "api_key": "<api-key>",
    "encoded": "<encoded>"
}
$client = ClientBuilder::create()
->setApiKey('<id>', '<api_key>')
->build();

Using babenkoivan/elastic-client

If you use babenkoivan/elastic-client, publish the config file and go to elastic.client.php and add it under your connections to use the encoded key - it includes both id and api key.

<?php declare(strict_types=1);

return [
    'default' => env('ELASTIC_CONNECTION', 'default'),
    'connections' => [
        'default' => [
            'hosts' => [
                env('SCOUT_ELASTIC_HOST', 'localhost:9200'),
            ],
           'apiKey' => [
              '<encoded>
              ]
        ],
    ],
];