Сервис Amazon ElasticSearch Несоответствие подписи для запроса PUT — Amazon SDK php V2

Я использую сервис Amazon ElasticSearch, и когда я пытался создать Запрос SignatureV4, он отлично работает для поисковых операций (GET Requests). Но когда я попытался выполнить некоторые операции, такие как создание индексов (используя запрос PUT), это произойдет из-за ошибки несоответствия подписи.

Я использую библиотеку Amazon SDK версии 2 SignatureV4 для подписания запросов. Также создан пользовательский обработчик Elasticsearch для добавления токенов в запрос.

У кого-нибудь есть такая проблема с библиотекой SignatureV4 в Amazon SDK php V2.

{"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the  service documentation for details.\n\nThe Canonical String for this request should have been\n'PUT\n/test_index_2\n\nhost:search-test-gps2gj4zx654muo6a5m3vxm3cy.eu-west-1.es.amazonaws.com\nx-amz-date:XXXXXXXXXXXX\n\nhost;x-amz-date\n271d5ef919251148dc0b5b3f3968c3debc911a41b60ef4e92c55b98057d6cdd4'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\XXXXXXXXXXXX\n20170511/eu-west-1/es/aws4_request\n0bd34812e0727fba7c54068b0ae1114db235cfc2f97059b88be43e8b264e1d57'\n"}

1

Решение

Этот твик нужен только пользователям, которые все еще используют Amazon SDK PHP версии 2. В версии 3 он поддерживается по умолчанию.

Для подписанного запроса я обновил текущий обработчик клиента elsticsearch, добавив промежуточное ПО для подписания запроса.

$elasticConfig = Configure::read('ElasticSearch');
$middleware = new AwsSignatureMiddleware();
$defaultHandler = \Elasticsearch\ClientBuilder::defaultHandler();
$awsHandler = $middleware($defaultHandler);

$clientBuilder =  \Elasticsearch\ClientBuilder::create();
$clientBuilder->setHandler($awsHandler)
->setHosts([$elasticConfig['host'].':'.$elasticConfig['port']]);
$client = $clientBuilder->build();

Я использовал следующую библиотеку для этой цели

use Aws\Common\Credentials\CredentialsInterface;
use Aws\Common\Signature\SignatureInterface;
use Guzzle\Http\Message\Request;

class AwsSignatureMiddleware
{
/**
* @var \Aws\Credentials\CredentialsInterface
*/
protected $credentials;

/**
* @var \Aws\Signature\SignatureInterface
*/
protected $signature;

/**
* @param CredentialsInterface $credentials
* @param SignatureInterface $signature
*/
public function __construct()
{
$amazonConf = Configure::read('AmazonSDK');
$this->credentials = new \Aws\Common\Credentials\Credentials($amazonConf['key'], $amazonConf['secret']);
$this->signature = new \Aws\Common\Signature\SignatureV4('es', 'eu-west-1');
}

/**
* @param $handler
* @return callable
*/
public function __invoke($handler)
{
return function ($request)  use ($handler) {
$headers = $request['headers'];
if ($headers['host']) {
if (is_array($headers['host'])) {
$headers['host'] = array_map([$this, 'removePort'], $headers['host']);
} else {
$headers['host'] = $this->removePort($headers['host']);
}
}
if (!empty($request['body'])) {
$headers['x-amz-content-sha256'] = hash('sha256', $request['body']);
}

$psrRequest = new Request($request['http_method'], $request['uri'], $headers);
$this->signature->signRequest($psrRequest, $this->credentials);
$headerObj = $psrRequest->getHeaders();
$allHeaders = $headerObj->getAll();

$signedHeaders = array();
foreach ($allHeaders as $header => $allHeader) {
$signedHeaders[$header] = $allHeader->toArray();
}
$request['headers'] = array_merge($signedHeaders, $request['headers']);
return $handler($request);
};
}

protected function removePort($host)
{
return parse_url($host)['host'];
}
}

Точная линия, которую я настроил для этой цели:

if (!empty($request['body'])) {
$headers['x-amz-content-sha256'] = hash('sha256', $request['body']);
}

Для запросов PUT и POST хэш полезной нагрузки был неправильным, потому что я не учитывал тело запроса при создании полезной нагрузки.

Надеюсь, что этот код полезен для всех, кто использует Amazon SDK PHP версии 2 и использует аутентификацию на основе IAM для службы Elasticsearch Hosted в облаке Amazon.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]