Edited at

IAM Roleを使ってAWS ElasticSearch ServiceのデータをLaravelで取得する

More than 1 year has passed since last update.

ESデータをIAM Roleで取得する方法です。

ESのポリシーがガチガチじゃないかたはこちら=>AWS ElasticSearch ServiceのデータをPHPで取得する


はじめに

PHPが稼働しているサーバーに以下環境変数を設定して下さい。

AWS_ACCESS_KEY_ID

AWS_SECRET_ACCESS_KEY

AWS_DEFAULT_REGION


AWS側の設定

Amazon Elasticsearch Serviceポリシー例

上記で設定したユーザーでみGETで取得が出来るように設定します。

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:user/xxx"
},
"Action": "es:ESHttpGet",
"Resource": "arn:aws:es:ap-northeast-1:000000000000:domain/xxx/*"
}
]
}


Composerでインストール

AWS-SDK、ClientBuilder、接続に必要なものをインストールします。


composer.json

"require": {

"aws/aws-sdk-php-laravel": "~3.0",
"elasticsearch/elasticsearch": "~6.0",
"guzzlehttp/guzzle": "^6.0",
"psr/http-message": "^1.0"
}

$ composer update

参考サイト=>Amazon Elasticsearch Service 検索リクエストへの署名


aws-sdk-php-laravelの設定

READMEを参考に先ほど設定した環境変数を読み込むためにconfig/app.phpにprovidersaliasesを設定します。

参考サイト=>GitHub aws/aws-sdk-php-laravel


config/app.php

'providers' => array(

// ~
Aws\Laravel\AwsServiceProvider::class,
)
// ~
'aliases' => array(
// ~
'AWS' => Aws\Laravel\AwsFacade::class,
)

以下を実行するとconfig/aws.phpが生成されます。

$ php artisan vendor:publish --provider="Aws\Laravel\AwsServiceProvider"

うまくできない人は以下のコマンドを先に入力すると解決するかもしれません。

$ php artisan config:clear

生成されたconfig/aws.phpにて設定した環境変数を読み込むように上書きします。


config/aws.php

return [

'credentials' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
],
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
];


PHP側から読み込み

リクエスト署名を挿入してClientBuilderに接続します。

途中でPromise rejectエラーなど出た場合はコメントアウト部分を表示してみるとエラー詳細が出ると思います。

Promiseって何という方はこちらを参考にすると良いかもしれません。

参考サイト=>Promiseについて0から勉強してみた


xxx.php

use AWS;

use Aws\Credentials\CredentialProvider;
use Aws\Signature\SignatureV4;
use Elasticsearch\ClientBuilder;
use GuzzleHttp\Ring\Future\CompletedFutureArray;
use GuzzleHttp\Psr7\Request as psr7Request;
use GuzzleHttp\Psr7\Uri;
//use Psr\Http\Message\ResponseInterface;

$psr7Handler = Aws\default_http_handler();

$signer = new SignatureV4('es', env('AWS_DEFAULT_REGION'));

$credentialProvider = CredentialProvider::defaultProvider();

$handler = function (array $request) use ($psr7Handler, $signer, $credentialProvider)
{
$request['headers']['Host'][0] = parse_url($request['headers']['Host'][0], PHP_URL_HOST);

$psr7Request = new psr7Request(
$request['http_method'],
(new Uri($request['uri']))
->withScheme($request['scheme'])
->withHost($request['headers']['Host'][0]),
$request['headers'],
$request['body']
);

$signedRequest = $signer->signRequest(
$psr7Request,
call_user_func($credentialProvider)->wait()
);

$response = $psr7Handler($signedRequest)->wait();
/*$response = $psr7Handler($signedRequest)->then(
function(Psr\Http\Message\ResponseInterface $r) {
return $r;
}, function($error) {
return $error['response'];
}
)->wait();*/

return new CompletedFutureArray([
'status' => $response->getStatusCode(),
'headers' => $response->getHeaders(),
'body' => $response->getBody()->detach(),
'transfer_stats' => ['total_time' => 0],
'effective_url' => (string) $psr7Request->getUri(),
]);
};

$hosts = [
'https://xxx.ap-northeast-1.es.amazonaws.com:443'
];

$client = ClientBuilder::create()->setHandler($handler)->setHosts($hosts)->build();

$params = [
'index' => '*'
];

$response = $client->search($params);


$responseにデータ返ってきていると思います。

参考サイト=>AWS ElasticSearch Service の認証にIAM Roleを使う [PHP編]