1

I want to connect my Shopware 6.4 installation to an Elasticsearch instance. My Elasticsearch instance is secured by username and password.

I can not establish a connection between Shopware 6 and Elasticsearch, because i can not find a way to pass username and password to the configuration.

.env

SHOPWARE_ES_HOSTS="http://username:password@elasticsearch.local:9201"
SHOPWARE_ES_ENABLED="1"
SHOPWARE_ES_INDEXING_ENABLED="1"
SHOPWARE_ES_INDEX_PREFIX="sw"

When running bin/console es:status i get a 401 status code.

Unknown 401 error from Elasticsearch null

When i try to connect via curl to my Elasticsearch instance, i can connect without a problem:

curl -u 'user:password' http://elasticsearch.local:9201
{

  "name" : "elasticsearch",
  "cluster_name" : "es-cluster-01",
  "cluster_uuid" : "dRsu0d_PQKyTI5RDe_r79Q",
  "version" : {
    "number" : "7.14.1",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "66b55ebfa59c92c15db3f69a335d500018b3331e",
    "build_date" : "2021-08-26T09:01:05.390870785Z",
    "build_snapshot" : false,
    "lucene_version" : "8.9.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

How can i pass username and password in Shopware to connect to my Elasticsearch instance?

Roman
  • 2,530
  • 2
  • 27
  • 50

1 Answers1

2

The config is passed via

   config/services/defaults.xml:12

to the client:

   <service id="Elasticsearch\Client" public="true">
        <factory class="Shopware\Elasticsearch\Framework\ClientFactory" method="createClient" />
        <argument>%elasticsearch.hosts%</argument>
        <argument type="service" id="shopware.elasticsearch.logger" />
        <argument>%kernel.debug%</argument>
    </service>

The hosts as passed to the clientbuilder:

 \Shopware\Elasticsearch\Framework\ClientFactory::createClient

According to

Specify elasticsearch username/password with Elasticsearch-PHP ClientBuilder

it use possible to have a user and pass there.

There is:

vendor/elasticsearch/elasticsearch/src/Elasticsearch/ClientBuilder.php:676

$host = $this->extractURIParts($host);

And:

/**
 * @throws InvalidArgumentException
 */
private function extractURIParts(string $host): array
{
    $parts = parse_url($host);

    if ($parts === false) {
        throw new InvalidArgumentException(sprintf('Could not parse URI: "%s"', $host));
    }

    if (isset($parts['port']) !== true) {
        $parts['port'] = 9200;
    }

    return $parts;
}

This is just a parse_url call which should extract user and pass.

Long story short: You approach actually should work.

For further debugging I suggest to xdebug into

 \Elasticsearch\ClientBuilder::extractURIParts

or put some temporary debug code:

private function extractURIParts(string $host): array
{
    $parts = parse_url($host);

    var_dump($parts); die();

Does you username or password maybe have some special characters which might cause problems?

Update - Solution found The problem was a special character in the password. Special characters like $ need to be escaped in the .env file.

If the password is 123$123 then the correct string would be:

SHOPWARE_ES_HOSTS="http://username:123\$123@elasticsearch.local:9201"

So the $ needs to be escaped by a backslash (\).

EDIT: the passwort might also be URL encoded! So if you see %21 in the .env it might actually be a ! sign.

Alex
  • 32,506
  • 16
  • 106
  • 171
  • Thanks your great explanation. i debugged it down yesterday until the clientbuilder. With your help i figured it that the special-character `$` in the password does make a problem. I will work on that now. ✌️ Thank you. – Roman Sep 23 '21 at 14:46
  • 1
    Yes, dollar needs to be escaped always in the `.env` https://stackoverflow.com/questions/62391986/variable-in-env-not-the-same-after-loading-through-symfony-dotenv – Alex Sep 24 '21 at 05:34