@ITスマホ×クラウド連載 第2回 AWS×Android:補足記事(2)Token Vending MachineとSecurity Token Service

Cronoloves

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。くろの(福田)です。

本記事は下記@IT連載「スマートフォンとクラウドをつなぐ技術カタログ 第2回 クラウド「AWS」とAndroidを直結するSDKで何ができるのか?」の補足記事です。下記記事の続きの内容になっております。

※忘れないようにメモ書き程度にメモっておいたものをブログにしたのですが、本文はとてもとても長くなってしまっております(汗)

■Token Vending Machineを利用したAndroidからAWSへのアクセス

Token Vending Machineを用いるとAndroid内にSecurity Credentialsを埋め込むことなくAWSにアクセスする事が出来ます。
今回はログインチェック等の処理が無いAnonymous Registration版のToken Vending Machineサンプルアプリケーション(以後TVM)を用いたAndroid端末からAWSへアクセスに関して取り上げます。

※Token Vending MachineのAWSの記事(本ブログ中にいくつかリンクさせて頂いています)のAWS Management Consoleのスクリーンショットが少し古いです。本ブログ内のスクリーンショットは執筆時点での最新版です。

まずは、その処理フローを見てみたいと思います。

▼Android端末からAWSへアクセスする際の流れ

  1. Android:AmazonTVMClinetクラスを通じてAmazon Elastic Beanstalk上にデプロイされているTVMへTemporary Security Creadentials取得リクエストを行う。
  2. TVM:今回はログインチェック等の処理は無い(実案件ではここでIdentity Federationを用いた権限チェックを行う)
  3. AWS:AWS Security Token Serviceから特定の権限を持つTemporary Security Creadentialsが振り出される。
  4. TVM:(図のフローはここから)TVMは受け取ったTemporary Security CreadentialsをAndroid端末に返す。
  5. Android:取得したTemporary Security Creadentialsを用いてS3等にアクセスする。
    • その際に、AWS SDK for Androidで提供されているクライアントクラス(図の例でのAmazonS3)を用いる。

※上記の処理フロー図は下記AWS記事内の図を書き直してみたものです。

■Token Vending MachineサンプルJavaアプリケーションを動かす

まず、Android端末からアクセスするTVMサンプルアプリケーションをBeanstalk上にデプロイします。

▼TVM ZIPファイルのダウンロード

下記サイト上部のDonwloadからTVMサンプルアプリケーションのZIPファイルをダウンロードします。

▼TVM用のIAMユーザーを作成する

  • AWS Management ConsoleのIAMタブを開く。
  • NavigationでUsersを選び、上部の「Create New Users」ボタンをクリックする。
  • ユーザー名を「TVMUser」として新規作成する。
  • Creadentialsがダウンロードできるので、ダウンロードして保存しておく。
  • ユーザー一覧で、作成したユーザーを選択し、下部のプロパティパネルの「Permissions」タブをクリックする。
  • ユーザーのパーミッションを設定するために、「Attach User Policy」をクリックする。
  • 「Custom Policy」を選択して、「Select」ボタンをクリックする。
  • 下記サンプルポリシーを「Policy Document」テキストエリアに入力して、「Apply Policy」ボタンをクリックする。
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:GetFederationToken",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iam:GetUser",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "sdb:*",
      "Resource": "*"
    },
    {
      "Effect":"Allow",
      "Action":"dynamodb:*",
      "Resource":"*"
    },
    {
      "Effect": "Allow",
      "Action": "sqs:*",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    },
    {
      "Action": "sns:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

ポリシーの意味:

  • STS(Security Token Service)よりTemporary Security Credentialsを取得する事が出来る。
  • IAMよりユーザー情報を取得する事が出来る。
  • SimpleDB、DynamoDB、SQS、S3、SNSを利用する事ができる。

ポリシーサンプル及び、手順はTVM ZIPがダウンロードできるページにあるものと同じです。

▼(よこみち)筆者が気になったSecurity Token ServiceからのCredentials取得処理

TVMサンプルアプリケーションはソースが提供されているので、STSからCredentialsを取得する処理のソースを確認してみたいと思います。

com.amazonaws.tvm.TemporaryCredentialManagement.java

	public static Credentials getTemporaryCredentials( String username ) {
		if ( ( Configuration.AWS_ACCESS_KEY_ID == null ) || ( Configuration.AWS_SECRET_KEY == null ) || username == null ) {
			return null;
		}
		else {
			try {
				BasicAWSCredentials creds = new BasicAWSCredentials( Configuration.AWS_ACCESS_KEY_ID, Configuration.AWS_SECRET_KEY );
				AWSSecurityTokenServiceClient sts = new AWSSecurityTokenServiceClient( creds );
				
				GetFederationTokenRequest getFederationTokenRequest = new GetFederationTokenRequest();
				getFederationTokenRequest.setName( username );
				getFederationTokenRequest.setPolicy( TemporaryCredentialManagement.getPolicyObject() );
				getFederationTokenRequest.setDurationSeconds( new Integer( Configuration.SESSION_DURATION ) );
				
				GetFederationTokenResult getFederationTokenResult = sts.getFederationToken( getFederationTokenRequest );
				return getFederationTokenResult.getCredentials();
			}
			catch ( Exception exception ) {
				log.log( Level.SEVERE, "Exception during getTemporaryCredentials", exception );
				return null;
			}
		}
	}

8行目のAWSSecurityTokenServiceClientを利用してCredentialsを取得しています。指定したリクエストを行う専用のDTO(GetFederationTokenRequest)も用意されているので非常に楽ですね。最後に15行目のsts.getFederationTokenでCredentialsを取得しています。12行目でポリシーの設定をしています。実案件ではたとえばAさんはS3にアクセスできる、BさんはEC2にアクセスできるといったようにユーザーに応じて、ビジネスロジックに応じて異なるポリシーが設定でき、それにより異なるCredentialsがSTSより発行されます。

※実際にTVMよりAndroid端末に割り当てられるCredentialsのポリシーのテンプレート

TokenVendingMachinePolicy.json

{"Statement":
    [
        {"Effect":"Allow","Action":["s3:*", "sdb:*", "sqs:*", "sns:*", "dynamodb:*"],"Resource":"*"},
        {"Effect":"Deny","Action":"sdb:*","Resource":["arn:aws:sdb:__REGION__:__ACCOUNT_ID__:domain/__USERS_DOMAIN__","arn:aws:sdb:__REGION__:__ACCOUNT_ID__:domain/__DEVICE_DOMAIN__"]},
        {"Effect":"Deny","Action":"iam:*","Resource":"*"}
    ]
}

▼AWS Elastic Beanstalkアプリケーションの作成

それでは予めダウンロードしておいたTVMサンプルJavaアプリケーションをBeanstalkにデプロイしましょう。Beanstalkですので、WARをアップロードして少し設定を行えば、アプリのデプロイは完了です!

アプリケーション名とWARファイルの指定:

  • AWS Management Consoleを開き、(一番左の)Elastic Beanstalkタブを開く。
  • 「Launch Application」ボタンをクリックする。すでにBeanstalkアプリがある場合は、右上の「Create New Application」ボタンで開始する。
  • アプリケーションの名前と、先ほどダウンロードしたWARファイル(AnonymousTVM.war)を指定して「Continue」ボタンをクリックする。

アプリケーションの詳細の指定

  • Environt名、URLを指定します。

EC2のインスタンスタイプの設定

  • インスタンスタイプとしてt1.microを指定します。

最後に、設定を確認して「Finish」ボタンをクリックします。

すると、アプリケーションの実行環境が自動的に構成されていって、しばらくするとアプリケーションが起動します。

上記のアプリケーションの概要(Overview)タブに、URLが表示されているので、これをクリックしてアプリケーションのインデックスページを確認します。

▼TVM Androidデモアプリケーションを実行する

最後に、AWS SDK for Androidに同梱されているサンプルアプリケーションであるAWSAndroidDemoTVMを実行して、TVMと連携してAWSにアクセスしたいと思います。

AWS SDK for Androidのサンプルはローカルにあると思いますので、Eclipseへインポートします。サンプルのプロジェクト名は「AWSAndroidDemoTVM」とします。

次にビルドパスの修正を行います。AWSAndroidDemoの場合と異なり、Credentialsをアプリに埋め込む必要は無く、AWSAndroidDemoTVMの場合は、アプリ内でAWS上のTVMアプリケーションのURLを指定します。

具体的にはAwsCredentials.propertiesを開いて、tokenVendingMachineURLに先ほどBeanstalkにデプロイしたTVMアプリケーションのURLを指定します。

例:tokenVendingMachineURL=xxx-mytvm.elasticbeanstalk.com

アプリケーション実行の準備が出来たので、エミュレータ/実機で実行してみます。

補足記事(1)で取り上げましたが、上図はSimpleDBのドメインの一覧を表示しています。アプリのタイトルがAWS DemoからAWS Demo TVMに代わっています。

また、作った覚えのないドメイン「TokenVendingMachine_DEVICES」が作成されています。これはTVMアプリケーションが利用する端末を管理するドメインになります。
下記のようにSimpleDBのドメインの中をSdbNavigatorで見てみても、このテーブルにアプリケーションが作成したデバイスの(ランダムな)IDとキーが保存されているのが分かります。

Android側の実際の処理の流れは、

  • AmazonTVMClient経由で端末を登録する:AmazonTVMClient.anonymousRegister()
  • AmazonTVMClient経由でトークンを取得する:AmazonTVMClient.getToken()

getToken()メソッド内で、アクセスキーとシークレットアクセスキーが取得されています。

最後に

TVMは今回取り上げたユーザー認証無し版以外に、ユーザー登録があるバージョン(AWSAndroidDemoTVMIdentity)も提供されています。こちらもこれまでの手順同様の流れで動作させられますので、ぜひ試してみて下さい。

※サンプルを動かし終わったら、Beanstalk上のアプリケーションを削除しておいて下さい。

おしまい

@Cronoloves

AWS Cloud Roadshow 2017 福岡