Search code examples
phpelasticsearchshopware

Connecting Elasticsearch with Username + password in Shopware 6


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:[email protected]: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?


Solution

  • 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\[email protected]: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.