AWSで、別のアカウントにあるリソースを使いたい場合、StsClientのAssumeRoleを使ってcredentialを取得して、そのもらったCredentialを使ってアクセスすることで実現できますが、いくつかハマった点がありましたので共有します。
まず、実際の動かし方については下記のコードのようにすると実現できます。(公式サイトより引用)
$stsClient = new Aws\Sts\StsClient([
'profile' => 'default',
'region' => 'us-east-2',
'version' => '2011-06-15'
]);
$ARN = "arn:aws:iam::123456789012:role/xaccounts3access";
$sessionName = "s3-access-example";
$result = $stsClient->AssumeRole([
'RoleArn' => $ARN,
'RoleSessionName' => $sessionName,
]);
$s3Client = new S3Client([
'version' => '2006-03-01',
'region' => 'us-west-2',
'credentials' => [
'key' => $result['Credentials']['AccessKeyId'],
'secret' => $result['Credentials']['SecretAccessKey'],
'token' => $result['Credentials']['SessionToken']
]
]);
ですが、実はこれだけでは不足。
AssumeRoleの呼び出し制限は結構厳しいので、むやみやたらと呼ぶと制限(クォータ)に引っかかって、レスポンスが返ってこなくなります。
ということで、発行された$result[‘Credentials’]をキャッシュに保存して普段はそれを使うようにする必要があるようです。
認証情報は、デフォルトで1時間有効なので、余裕を見てキャッシュの有効期限は30分程度にしておけば、30分に1回しか呼ばれないので問題なく利用できるはずです。
ちなみに、デプロイ先としてLambdaを使った場合、キャッシュの保存先をファイルにすると、リクエストが増えると別のインスタンスで実行されてキャッシュが効かなくなることがあるようです。時間がたてばまたアクセスできるようになりますが、一度この状態になると、ユーザーがリロードを繰り返すなどをして、余計にクォータを消費してしまいかねません。
よって、大量アクセスが発生するサイトの場合はDBなりredisなりをつかって、インスタンスをまたいでキャッシュにアクセスできるような仕組みにしておいた方が安全かと思います。
言うまでもありませんが、Credentialは超機密情報なので、外部からアクセスができないように注意しましょう。キャッシュにredisを使う場合、外部からアクセスできるような設定にしないようにしましょう。