elasticsearch-php icon indicating copy to clipboard operation
elasticsearch-php copied to clipboard

connecting to elasticsearch fails when password contains the special character '@'

Open hamzamogni opened this issue 2 years ago • 5 comments

Summary of problem or feature request

When the elasticsearch password contains the character @ then authentication fails.

This is my code that setups the client:


$client = Elastic\Elasticsearch\ClientBuilder::create()
                                ->setHosts(["https://elasticsearch:9200"])
                                ->setCABundle("/var/www/html/certs/ca/ca.crt")
                                ->setBasicAuthentication("elastic", "test@2022")
                                ->build();

When I then run $client->info() I get the following error

Elastic\Transport\Exception\NoNodeAvailableException with message 'No alive nodes. All the 1 nodes seem to be down.'

So I then attached a logger to the client and got the following log message:

[2022-06-23T01:16:14.246516+00:00] name.ERROR: Retry 0: cURL error 6: Could not resolve host: 2022@elasticsearch (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://elastic:test@2022@elasticsearch:9200/ [] []

So it seems like the @ character is not connected and thus it gets mixed with the actual host. So here the client is trying to connect to 2022@elasticsearch instead of elasticsearch

System details

  • Operating System: Arch Linux
  • PHP Version 8.0.2
  • ES-PHP client version 8.0
  • Elasticsearch version 8.1.3

hamzamogni avatar Jun 23 '22 01:06 hamzamogni

After some digging I found out a fix could be to urlencode username and password before passing them to elastic Transport?

It could be done in the ClientBuilder either when setting values of username and password, or inside the build function just before passing values to transport

// Basic authentication
if (!empty($this->username) && !empty($this->password)) {
    $transport->setUserInfo(urlencode($this->username), urlencode($this->password));
}

I don't know if this is the right approach to fix this, or even if this is something that this package should handle. I am open for further directions.

Thank you.

hamzamogni avatar Jun 23 '22 12:06 hamzamogni

@hamzamogni the issue is related to the implementation of Uri::withUserInfo() with the PSR-7 client library installed (nyholm/psr7, guzzle, etc). To avoid different bechaviours we can definitely use an approach like the one that you suggested using urlencode(). DId you try the fix?

We should fix this in elastic/elastic-transport-php that is the library used by elasticsearch-php for the HTTP transport. In particular, we should fix this in Transport::setupUserInfo function.

ezimuel avatar Jun 29 '22 10:06 ezimuel

@ezimuel Thank you for your reply. Yes, I have tried the fix I mentioned in my previous comment, I agree that the fix would be better implemented in elastic/elastic-transport-php.

I would suggest something like this be implemented in Transport::setupUserInfo

    /**
     * Setup the user info, if not already present
     */
    private function setupUserInfo(RequestInterface $request): RequestInterface
    {
        $uri = $request->getUri();
        if (empty($uri->getUserInfo())) {
            $encodedUser = urlencode($this->user);
            $encodedPassword = urlencode($this->password);

            if (isset($this->user)) {
                $request = $request->withUri($uri->withUserInfo($encodedUser, $encodedPassword));
            }
        }
        return $request;
    }

I can send a PR to elastic/elastic-transport-php if you think this is a good fix!

Thank you.

hamzamogni avatar Jun 29 '22 11:06 hamzamogni

@hamzamogni yes, you can send the PR, thanks!

ezimuel avatar Jun 29 '22 13:06 ezimuel

@ezimuel Thank you for the support.

hamzamogni avatar Jun 29 '22 13:06 hamzamogni