[AWS][Android] Amazon Cognito のモバイルユーザー認証を使って、AndroidからAWSリソースを利用してみた。
Amazon Cognito
今回は、Cognitoを利用してAWSリソースが利用できるようなので、androidでその辺りを調査してみました。
[以下、公式より引用] Amazon Cognito を使用すると、AWS のセキュリティのベストプラクティスを簡単に実装できます。Amazon Cognito を使用すると、アプリケーションの各ユーザーには、Amazon S3 や Amazon DynamoDB といった他の AWS サービスにアクセスするために使用できる、権限の制限された一時的な AWS 認証情報 1 揃いが付与されます。つまり、アプリケーションでセキュリティ認証情報のハードコーディングを行わなくても、アプリケーションから必要なリソースにアクセスできることになり、ユーザーに優れた体験を提供できます。
とりあえず使ってみる
Amazon Congnitoを利用する(Poolの作成)
Cognitoを利用するにはCognito identity pool というのを作成します。 作成方法はこちらを参照してください。 [AWS][iOS] Amazon Cognito のモバイルユーザー認証 & データ同期 を iOS で使ってみた
利用料金は、無料利用枠内であれば、1か月につき 10GB の容量と100万回の同期オペレーションが利用できます。 詳細についは、公式ページをご確認ください。
SDKのインポート
まずは、こちらから AWS SDK for Androidをダウンロードします。
aws-android-sdk-2.0.5-core.jarをプロジェクトにインポートします。
後は、ネットワーク接続が必要なのでパーミッションを追加しておきます。
<uses-permission android:name="android.permission.INTERNET"/>
Credentialsを取得してみる
ひとまず、サンプルコードを参考に以下のようにしてみました。 How to Authenticate Users
import android.app.Activity; import android.os.Bundle; import android.util.Log; import com.amazonaws.android.auth.CognitoCredentialsProvider; import com.amazonaws.auth.AWSSessionCredentials; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); (new Thread(new Runnable() { @Override public void run() { CognitoCredentialsProvider cognitoProvider = new CognitoCredentialsProvider( MainActivity.this, // get the context for the current activity "XXXXXXXXXXXX", // AWS Account ID "us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX", // Identity Pool ID "arn:aws:iam::XXXXXXXXXX:role/YourAuthRoleName", // AuthRoleName "arn:aws:iam::XXXXXXXXXX:role/YourUnauthRoleName" // UnauthRoleName ); AWSSessionCredentials credentials = cognitoProvider.getCredentials(); Log.d("credentials" , "accessKey:" + credentials.getAWSAccessKeyId()); Log.d("credentials" , "secretKey:" + credentials.getAWSSecretKey()); } })).start(); } }
CognitoCredentialsProviderのコンストラクタに、AWS Account ID, Identity Pool ID, Role ARNを設定します。 Identity Pool ID は Cognito の [Edit Identity Pool] 内に表示されています。 Role ARNは、IAM メニュー内の[Roles]をクリックし、Cognitoの登録時に作成されたRole名をクリックすると、一番上に表示されています。
CognitoProvider#getCredentials()では、非同期での処理が必要になりますので、簡単ですがとりあえずThreadで実装しました。
実行すると、CognitoProvider#getCredentials()で取得したCredentialsのAccess_KeyとSecret_Keyがログに表示されると思います。
ログを見ると、SharedPreferencesにキャッシュされるようですね。ちなみに、ライブラリのソースコードをのぞいたら、1時間毎に更新されるようでした。
AWSリソースを利用する
Access_KeyとSecret_Keyが取得できたということは、これでAWSリソースにもアクセスできますね!
それでは試しに、先日書いたブログのソースを変更して、kinesisにアクセスしてみます。
private AmazonKinesisClient kinesisInit() { // String accessKey = "xxxxxxxxxx"; // String secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxx"; // // AWSCredentials credentials = new BasicAWSCredentials(accessKey,secretKey); CognitoCredentialsProvider cognitoProvider = new CognitoCredentialsProvider( getActivity(), // get the context for the current activity "XXXXXXXXXXXX", "us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX", "arn:aws:iam::XXXXXXXXXX:role/YourAuthRoleName", "arn:aws:iam::XXXXXXXXXX:role/YourUnauthRoleName" ); String endpoint = "https://kinesis.ap-northeast-1.amazonaws.com"; AmazonKinesisClient client = new AmazonKinesisClient(cognitoProvider); client.setEndpoint(endpoint); return client; }
これで実行してみたら、どうでしょう? 動きましたか?
落ちますね。。。 おそらく、権限がないと怒られることでしょう。
Roleに権限を追加
デフォルトで作成した、CognitoのユーザロールはCognito以外のアクセス権限がないので、権限を追加します。
IAM のメニューから [Roles]を選択し、Cognito登録時に作成したRole名を選択します。(今回は Facebookなどの認証をしていないので、UnauthのRoleだけで大丈夫です。)
Attach Role Policyから、 Amazon Kinesis Full Accessを追加します。 (実運用などで厳密にやる場合はPolicy GeneratorなどでAction毎に権限を付与した方がいいと思います。)
これで、再度実行するとちゃんと接続できました。
まとめ
世の中には、このようなAWSアカウントの乗っ取りもあるようなので、Access_KeyとSecret_Keyの取り扱いには十分注意したほうがいいですね。 上記のようなgithub以外でも、アプリのソースコードにハードコーディングしている場合は、アプリを解析された場合に同じことが起こるので、こちらも注意が必要です。(自分でサンプルコード書いておいてアレですが。。。) 特にAndroidでは、ソースコードを簡単に解析される可能性があるのでセキュリティ関連は、より注視していきたいですね。
以上です