本記事はcloudpack あら便利カレンダー2017の06/07(水)の記事です。
AWSアカウント:プロジェクト = 1:n
なSaaSをβでリリースしてたけど、本番稼働にあたってAWSの請求情報わけられないじょん!
っていうヤバさを解決したい人生でした。
経緯
S3(Web) - EC2(API) - Device Farm
ユーザ認証:Cognito User Pools/DynamoDB
- ひとつのアカウント内のDevice FarmをSaaSで提供したい
- こんな感じのアーキテクチャ構想で組んで、これでいけるぜ!ってなった
- Device Farmには複数のProjectを立てることができる
- Cognitoに登録したユーザとProjectのヒモ付はDynamoDBで行っている
- サービスの課金形態的に、Projectごとの利用時間を計算する必要がある
- そんなことすっかり忘れてた!!
- 四則演算絶対やりたくない == ズレたときに燃えるのが目に見えてる
- Device Farmを別のアカウントにわけちゃおうぜ!!
どうやって実現したか
AWSには、他アカウントのリソースにアクセスする仕組みが用意されているため、それを使って実現しました。
STSの仕組みについてはこちらを参考にしてください。
- Cognitoのログインユーザーを特定して
- それをキーにDynamoDBからRoleのARNをひいて
- そのアカウントのDeviceFarmClientを取得する
こうすることで、
- 請求情報はクライアント毎のアカウントに紐づくため請求処理も楽ちんに!!(ログインして請求情報見るだけ)
- 今までプログラム上で「このProjectはこのユーザと紐付けて...」みたいな認証処理が不要に!! == セキュアに!
みたいなメリットが得られました!便利だね!すごいね2017年!
結論
AWS STS AssumeRoleつかったクロスアカウントアクセスは便利
コードのっけておきます
なんとなくstaticなSingletonで実装しました。
呼び出し側.php
<?php
use App\AwsClient;
$arn = ''; // なんかしらとってくる
$DeviceFarmClient = AwsClient::DeviceFarm($arn);
return $DeviceFarmClient->listProjects()->toArray();
呼び出され側.php
<?php
namespace App;
use Aws\CognitoIdentityProvider\CognitoIdentityProviderClient;
use Aws\Credentials\AssumeRoleCredentialProvider;
use Aws\DeviceFarm\DeviceFarmClient;
use Aws\Sts\StsClient;
class AwsClient
{
private static $DeviceFarm;
private function __construct()
{
}
final function __clone()
{
throw new \Exception('__clone() is not allowed');
}
public static function DeviceFarm($arn = null)
{
if (!self::$DeviceFarm) {
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient([
'region' => 'us-west-2',
'version' => 'latest'
]),
'assume_role_params' => [
'RoleArn' => $arn,
'RoleSessionName' => 'service-' . time(),
]
]);
self::$DeviceFarm = new DeviceFarmClient([
'region' => 'us-west-2',
'version' => 'latest',
'credentials' => $assumeRoleCredentials
]);
}
return self::$DeviceFarm;
}
}
参考:http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/credentials.html#assume-role-credentials