twingo_b's blog

memo

IAM Roles for EC2 instancesを利用して、S3 Pre-signed URL生成/Direct Object Upload

AWS Advent Calendar 2012の9日目です。

IAM roles for EC2 instances(以下IAM roles)ってご存知でしょうか? AWSを利用して開発していると、どうしてもAccessKeyId/SecretAccessKeyの扱いに困りますよね?

IAM rolesを利用すると、このようにプログラムやコンフィグファイルに埋め込んでいたものが、

1
2
3
4
5
require_once 'AWSSDKforPHP/sdk.class.php';
$s3 = new AmazonS3(array(
  'key' => 'xxxxxx',
  'secret' => 'xxxxxx',
));

書かなくて良くなります^^

1
2
3
4
require_once 'AWSSDKforPHP/sdk.class.php';
$s3 = new AmazonS3(array(
  'default_cache_config' => '/tmp'
));

今回は、普段良く利用しているS3 Pre-signed URL生成/Direct Object UploadがIAM rolesでもちゃんと動くか検証しないとなーと前から思っていましたので、この機会にやってみることにしました。

前提条件

以下の環境で動作確認を行いました。

  • Amazon Linux AMI 2012.09
  • PHP 5.3.18
  • php-amazon-sdk-1.5.17

IAM rolesの作成

詳細は、クラスメソッド開発ブログさんのIAM roles for EC2 instancesって何?を参照されると良いと思います。今回S3を利用する上でポイントとなる部分を説明します。

特定のバケット以下のみアクセス権を与えたいので、Edit Permissionsで、下記のように設定しました。

特定のバケットのみ操作を許可したい場合でも、ListAllMyBucketsはすべて許可しておく必要があります。get_bucket_list()が失敗しますので。また、特定のバケット以下のみ許可する場合に、arn:aws:s3:::[bucket]arn:aws:s3:::[bucket]/*を両方書かないと、うまく動かなかったです^^;

生成されたjsonはこちらになります。

EC2インスタンスの起動

ここもポイントだけ。Launch Instance時はClassic Wizardを選ばないと、IAM Roleを選べなかったです。

セットアップ

最低限、必要なものだけインストールしました。

1
sudo yum -y install php httpd php-amazon-sdk

S3 Pre-signed URL生成

ここからが本題です。

サンプルコードはこちらです。とってもシンプルですね。

実行すると、このように1分のみ有効なURLが生成されます。 プログラム埋め込み時は固定だったAWSAccessKeyIdも、定期的に変更されます^^

1
2
php get_object_url.php 
https://test-twingob.s3.amazonaws.com/test.txt?AWSAccessKeyId=ASIAJQ4QZDDBS22LYMGA&Expires=1355056156&Signature=Zq9j1K6eG9zDjzA7uUrgIRr2i10%3D&x-amz-security-token=AQoDYXdzEC0agALr%2BzwOiErKaI1Jd1kg7Ejc1zx5TpExGmaYG2VliSjiOX%2BHZ09j9397tnGlcKthKixDTUDf49tHssOxAuyLAK5vM5jjz%2BA6CM4jZUz43%2FN4BbMWI%2FnyN2Bdf96xGrkOp1puOqoXt0hk134%2BqUEySXtSFIds8S%2B4Ijn0Oa7hlaVykkhfcx6YErTOfS6mc6U3DjkxZB9P9ia6c%2FlGEFexUzNVYi1hvgxTshBHA8bi%2FMXqhLNeY5XoDJ13S4Ym8BxD0N2P0thlEMF80xb9WcRyhuFWn4xumUSbdWYAcvXbrKR9mwbeY0qeRRUzBBAwSM%2BJM4rH8X5tLQQs4OCC7bCVx0EJIJvpkYYF

Direct Object Upload

CDPのDirect Object Uploadパターンになります。PHPで簡単に実現する方法ないかなーと思って探していたら、S3BrowserUploadを見つけました!自分でpolicyやsignature生成しなくても良いので、とっても便利!でも落とし穴が^^;

IAM rolesでAPIを利用するときに必要なx-amz-security-tokenを自動で付与してくれないんですよね。付与しない状態で動かすと、

1
InvalidAccessKeyId

とエラーが出力されて、アップロードに失敗します。かなりググって悩みました。

サンプルコードはこちらです。x-amz-security-tokenが解決できれば、すごくシンプルに書くことができました。

実行すると、このようなHTMLが生成されます。このフォームも表示後1分のみ有効です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
curl http://localhost/post_object.php
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  </head>
  <body>
    <form action="http://test-twingob.s3.amazonaws.com/"
          method="POST"
          enctype="multipart/form-data">
    
                <input type="hidden" name="AWSAccessKeyId" value="ASIAJQ4QZDDBS22LYMGA">
                <input type="hidden" name="success_action_status" value="201">
                <input type="hidden" name="acl" value="private">
                <input type="hidden" name="Content-Disposition" value="attachment; filename=00000001.txt">
                <input type="hidden" name="Content-Type" value="text/">
                <input type="hidden" name="key" value="00000001.txt">
                <input type="hidden" name="success_action_redirect" value="http://twingo-b.github.com/?id=00000001">
                <input type="hidden" name="x-amz-security-token" value="AQoDYXdzEC0agALr+zwOiErKaI1Jd1kg7Ejc1zx5TpExGmaYG2VliSjiOX+HZ09j9397tnGlcKthKixDTUDf49tHssOxAuyLAK5vM5jjz+A6CM4jZUz43/N4BbMWI/nyN2Bdf96xGrkOp1puOqoXt0hk134+qUEySXtSFIds8S+4Ijn0Oa7hlaVykkhfcx6YErTOfS6mc6U3DjkxZB9P9ia6c/lGEFexUzNVYi1hvgxTshBHA8bi/MXqhLNeY5XoDJ13S4Ym8BxD0N2P0thlEMF80xb9WcRyhuFWn4xumUSbdWYAcvXbrKR9mwbeY0qeRRUzBBAwSM+JM4rH8X5tLQQs4OCC7bCVx0EJIJvpkYYF">
                <input type="hidden" name="policy" value="eyJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJ0ZXN0LXR3aW5nb2IifSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwMSJ9LHsiYWNsIjoicHJpdmF0ZSJ9LHsiQ29udGVudC1EaXNwb3NpdGlvbiI6ImF0dGFjaG1lbnQ7IGZpbGVuYW1lPTAwMDAwMDAxLnR4dCJ9LFsic3RhcnRzLXdpdGgiLCIkQ29udGVudC1UeXBlIiwidGV4dFwvIl0seyJrZXkiOiIwMDAwMDAwMS50eHQifSx7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjoiaHR0cDpcL1wvdHdpbmdvLWIuZ2l0aHViLmNvbVwvP2lkPTAwMDAwMDAxIn0seyJ4LWFtei1zZWN1cml0eS10b2tlbiI6IkFRb0RZWGR6RUMwYWdBTHIrendPaUVyS2FJMUpkMWtnN0VqYzF6eDVUcEV4R21hWUcyVmxpU2ppT1grSFowOWo5Mzk3dG5HbGNLdGhLaXhEVFVEZjQ5dEhzc094QXV5TEFLNXZNNWpqeitBNkNNNGpaVXo0M1wvTjRCYk1XSVwvbnlOMkJkZjk2eEdya09wMXB1T3FvWHQwaGsxMzQrcVVFeVNYdFNGSWRzOFMrNElqbjBPYTdobGFWeWtraGZjeDZZRXJUT2ZTNm1jNlUzRGpreFpCOVA5aWE2Y1wvbEdFRmV4VXpOVllpMWh2Z3hUc2hCSEE4YmlcL01YcWhMTmVZNVhvREoxM1M0WW04QnhEME4yUDB0aGxFTUY4MHhiOVdjUnlodUZXbjR4dW1VU2JkV1lBY3ZYYnJLUjltd2JlWTBxZVJSVXpCQkF3U00rSk00ckg4WDV0TFFRczRPQ0M3YkNWeDBFSklKdnBrWVlGIn1dLCJleHBpcmF0aW9uIjoiMjAxMi0xMi0wOVQxMjo1Njo1OVoifQ==">
                <input type="hidden" name="signature" value="xjyu5PRSm0mZLg5s6yvbH4FUY9I=">
            
        <input type="file" name="file">
        <input type="submit" name="upload" value="Upload">
    </form>
  </body>
</html>

さいごに

ちゃんと動いてよかった^^。動かなくてS3BrowserUploadのgithubのソースコード見てたら、authorがラスベガスのre:Inventでお会いしたJeremyさんでした。ちょっとほっこりした^^

iOS builder.pyのコマンドラインオプション

Titanium mobile “early” Advent Calendar 2012用小ネタ、2個目です。

めずらしくiOSネタです^^;

開発環境はMacで、shellはzshを利用しています。

普段はMakeTiを使ってるんですが、Distributeとかもコマンドラインでやりたいなと思いました。そのためだけにTitanium Studio立ち上げるのめんどくさいですし―。

そんな時は直接builer.pyを動かす必要があるんですが、コマンドラインオプションを調べようとヘルプを見ると、こんな感じでオプションがよくわからない。。Androidのbuilder.pyはまだわかるのに。

1
2
3
4
5
6
7
8
9
10
11
~/Library/Application\ Support/Titanium/mobilesdk/osx/2.1.3.GA/iphone/builder.py
builder.py <command> <version> <project_dir> <appid> <name> [options]

available commands:

  install       install the app to itunes for testing on iphone
  simulator     build and run on the iphone simulator
  adhoc         build for adhoc distribution
  distribute    build final distribution bundle
  xcode         build from within xcode
  run           build and run app from project folder

どうしたもんかなーと思っていると、build.logの最初にそれっぽい情報が!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# AdHocビルドのbuild.logの例
cd ~/path/to/[your titanium mobile Project]
head -n 30 build/iphone/build/build.log
================================================================================
Appcelerator Titanium Diagnostics Build Log
The contents of this file are useful to send to Appcelerator Support if
reporting an issue to help us understand your environment, build settings
and aid in debugging. Please attach this log to any issue that you report.
================================================================================

Starting build at 11/20/12 12:00

Build details:

   timestamp=10/02/12 16:16
   module_apiversion=2
   version=2.1.3
   githash=15997d0


Script arguments:
   /Users/$USER/Library/Application Support/Titanium/mobilesdk/osx/2.1.3.GA/iphone/builder.py
   adhoc
   6.0
   ~/path/to/[your titanium mobile Project]
   [appid]
   [name]
   [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]
   [証明書の名前]
   universal
   /Users/$USER/Library/Keychains/login.keychain

では、オプションに順番に入れたら動くかなーと思ってやってみたら、動きました!

1
2
security unlock-keychain /Users/$USER/Library/Keychains/login.keychain
/Users/$USER/Library/Application\ Support/Titanium/mobilesdk/osx/2.1.3.GA/iphone/builder.py "adhoc" "6.0" "~/path/to/[your titanium mobile Project]" "[appid]" "[name]" "[xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]" "[証明書の名前]" "universal" "/Users/$USER/Library/Keychains/login.keychain"

security unlock-keychain ~は、事前にやっとかないと、「SystemExit: 65」になりました。build.logの最後の方に「User interaction is not allowed.」と出てましたので判断できました。

ipaファイルは以下に出力されてました

1
~/path/to/[your titanium mobile Project]/build/iphone/build/Debug-iphoneos/[name].ipa

同じように、Distributeも試してみましたが、大丈夫そう!

これで、コマンドライン実行&自動化できそうですー。

第25回まっちゃ139勉強会に参加してきました

第25回まっちゃ139勉強会に参加して、とても勉強になったし、今後も使いそうなのでメモ。

Twitterのまとめはこちら

テーマは、「管理者のためのDNSセキュリティ勉強会」、私は到着が開始時間に全然間に合わず、鈴木常彦先生の講演から聞きました。

DNSセキュリティの詳細は、識者のかたに解説譲るとして、、

浸透いうな

鈴木先生が啓蒙されているDNSの「浸透いうな」について、これって仕方ないのかなとずっと思ってたんですが、実はちゃんと運用できていないだけと聞いて、結構衝撃でした^^;

具体的には、「浸透いうな!」や「JPRSの資料、DNSサーバーの引っ越し」を講演中にググって確認してました。

実際に私が経験したものは、「浸透いうな(その3):まずいNS設定」の状況が起きていたんじゃないかなと。

今後もName Serverの切替する事あるでしょうし、外部に切替を依頼するときに前提条件として理解しておけば、無用なトラブルを避けられそうです。これらの資料、社内・社外共に共有したいです。

共有DNSサーバーのリスク

こちらも身近な脅威だなと思ったのでメモ。

サービス運用上の問題に起因するドメイン名ハイジャックの危険性について

これできちゃうと、メールを盗聴されたりしちゃいますよね。。今メインで利用しているAWSのRoute53は比較的安全で、約2千台のサーバーを用意することで、サブドメインのサーバーが重複しないように力技で対策しているそうです。ただし、こういうご意見もいただきました。

まっちゃ139の勉強会メソッド

懇親会からの帰りに、代表のまっちゃだいふくさんとご一緒して、勉強会に参加されている方の間で、コミュニケーションが生まれるように工夫されている点をお聞きしたのでメモ。

  • 参加者全員の自己紹介タイム、今回参加者は、70名以上!
  • おやつ休憩
  • 質疑応答・ディスカッション
  • 懇親会

をスケジュールに組み込んでいるそうです。 特に自己紹介が有効で、その後各人のバックグラウンドがわかっているので、お話しやすいとのこと。今後の勉強会開催するときに、取り入れたいなと思いました。

以上、ぜひ次回も参加したいですー!

MakeTiをAndroidで利用する

Titanium mobile “early” Advent Calendar 2012用小ネタです。 @astronaughtsさんが困ってたので、他の方ももしかしたらハマるかなと^^;

開発環境はMacで、shellはzshを利用しています。

Andorid SDKTitanium Studioで必要なものはインストール済みの前提です。

MakeTiは@astronaughtsさんのgithubからcloneしてます。

MakeFileはAndroid SDKが$HOME直下にAndroidというディレクトリ名で存在することが前提で書かれています。 必要なファイル、ディレクトリにシンボリックリンクを貼って動くようにします。

それでは、実際に動かしてみましょう!

1
2
cd ~/path/to/[your titanium mobile Project]
make clean && make deploy platform=android

こんな感じで実機へのインストールがコマンドで実行できます。

うまく動かなかった方へ。

私みたいに2.0以前のTitanium Mobile SDKを利用していた方は、古いSDKを移動しておく必要があります。MakeTiが誤検知しちゃいますので。 SDKのインストール先が2.0から$HOME/Library/Application Support/Titaniumへ移動した影響ですねー。

1
sudo mv /Library/Application\ Support/Titanium /Library/Application\ Support/Titanium_OLD

ではでは〜。

Titanium MobileでDeployGateを利用する

@astronaughtsさんから依頼を受け、moduleを作成したところ、ひと通りうまく動作しました^^。

検証中にちょっとハマったところがあり、@DeployGate_jaさんにドキュメントの改善要望をお問い合わせしました。

その後、こんなお話をいただいたので、Octpressの練習も兼ねてmoduleの作成方法を公開します。

サンプルソースはGitHubに置いておきましたので、こちらをどうぞ。

Andorid SDKTitanium StudioDeployGateで必要なものはインストール済みの前提です。

開発環境はMacで、shellはzshを利用しています。

Titanium Mobileのandroid moduleの作成

~/.zshrc例

moduleを作成する

適当なディレクトリに移動して、.zshrcでalias指定したtitaniumコマンドでmoduleのテンプレートを生成します。

1
$ titanium create --platform=android --type=module --name=TiDeployGate --id=local.twingob.android.tideploygate --android=$ANDROID_SDK

Created android module projectと出れば成功です。

tideploygateディレクトリ以下にテンプレートが作成されました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
LICENSE
assets
- README
bin
build
build.properties
build.xml
dist
documentation
- index.md
example
- app.js
hooks
- README
- add.py
- install.py
- remove.py
- uninstall.py
lib
libs
manifest
platform
- README
src
- local
  - twingob
      - android
          - tideploygate
              - ExampleProxy.java
              - TideploygateModule.java
timodule.xml

build.xml,build.propertiesがローカルPATHを指しており、そのままではコード共有しにくいので修正します。Titanium Studio、Eclipseなどを利用する場合は.classpathも同様に修正したほうが良いです。

build.xmlの修正

build.propertiesから環境変数を参照できるように<property environment="env"/>を追加しました。

build.propertiesの修正

timodule.xmlの修正

example/app.jsからの動作確認時、リモートLogCatが利用できるように<uses-permission android:name="android.permission.READ_LOGS" />を記載しておきます。

AndroidManifest.xmlはこの記述から自動生成されます。

libディレクトリにdeploygatesdk.jarをコピーする

後ほど説明するantビルド時に、libディレクトリのjarが参照されます。

moduleのソースコード変更、DeployGateの呼び出し

コマンドから自動生成されるソースコードは下記2種類です。 src/local/twingob/android/tideploygate

1
2
- ExampleProxy.java
- TideploygateModule.java

不用なサンプルファイルを削除

今回はProxyは利用しないので、ExampleProxy.javaは削除します。

以降は、テンプレートをTitanium Studio、Eclipseにインポートしたほうがやりやすいかと思います。

TideploygateModule.javaの名前が気になるのでリファクタリング

TiDeployGateModule.javaに修正しました。

TiDeployGateModule#onAppCreate()にDeployGate#install()を追加

ここがTitanium MobileでDeployGateを利用する際のポイントになります。

TiDeployGateModule#onAppCreate()はApplication#onCreate()時に呼び出されます。

また、Titanium Mobileで生成されるAndroidManifest.xmlandroid:debuggableは常にfalseとなっています。

そのため、DeployGatei#install(Application app)ではなく、DeployGate#install(Application app, DeployGateCallback callback, boolean forceApplyOnReleaseBuild) を利用する必要があります。deploygatesdk-javadoc.jarにその旨記載がありました。

例では、forceApplyOnReleaseBuild:trueとなるように、DeployGate.install(app,null,true)と指定しました。

Android SDKをEclipseから開発ビルドした場合は、android:debuggabletrueになるみたいです。最初DeployGateのWeb上のドキュメントだけ見て、JavaDocを読んでなかったので、なぜ動かないのかわからず、ちょっとはまりました^^;。ドキュメントは最初にひと通り読まないとダメですよね><。

クラスのコンストラクタ以外のmethodサンプルを削除して、必要なmethodを追加

こちらはmoduleやDeployGateのサンプルの通りです。

example/app.jsを記載して、moduleの動作確認を行う

ant runで動作確認できるように、js側でmoduleを呼び出します。

moduleは、テンプレートのディレクトリ直下でantコマンドを実行すると、emulatorで動作確認ができるので、実行してみます。

Android emulatorの起動

1
$ ant run.emulator

Terminalの別のTabでテストビルド

1
$ ant run

無事アプリは起動したのですが、emulatorのLogCatに下記のように出力され、動作しませんでした。DeployGateのクライアントアプリのインストールが必要ということですよね。

1
DeployGate  V  DeployGate is not available on this device.

そこで、ant runしてできたapkをdgate pushして、実機で動作確認して見ることにしました。ant runのログの最後の方に下記のように出力されているので、それを使ってみます。

1
2
 [exec] [DEBUG] /Users/[user]/android-sdk/platform-tools/adb -e install -r /var/folders/3j/cjcy2jcd6tlbkqyv1crfj1yh0000gn/T/m0sWWDXti/tideploygate/build/android/bin/app.apk  
 [exec] [INFO] Launching application ... tideploygate
1
2
3
4
5
6
7
8
$ dgate push /var/folders/3j/cjcy2jcd6tlbkqyv1crfj1yh0000gn/T/m0sWWDXti/tideploygate/build/android/bin/app.apk
Push app file successful!

Name :          tideploygate
Owner :         twingo_b
Package :       local.twingob.android.tideploygate
Revision :      1
URL :           https://deploygate.com/users/twingo_b/apps/local.twingob.android.tideploygate?key=3cc6266d2d8a606a25dfcb209331bf5de954734a

無事Pushできたので、アプリを実機で起動してみます。

動いた!

リモートLogCatも動いた!

うまく動いてますね^^。

Titanium Mobileプロジェクトでの利用

実際のプロジェクトで利用するために、moduleのzipファイルを生成

ant distコマンドで、zipファイルを生成します。

1
2
3
4
5
6
7
8
9
10
$ ant dist
...
zip.libs:
      [zip] Updating zip: /Users/[user]/[path to dir]/tideploygate/dist/local.twingob.android.tideploygate-android-0.1.zip

zip.metadata:

post.dist:

BUILD SUCCESSFUL

distディレクトリ以下にできたzipファイルlocal.twingob.android.tideploygate-android-0.1.zipをTitanium Mobileプロジェクト直下にコピーします。

tiapp.xmlの修正

moduleの指定を追加します。リモートLogCatを利用する場合は、<uses-permission android:name="android.permission.READ_LOGS" />も記載します。

実際には、Distributeビルド(リリースビルド)の際、これらの記載は削除し、module自体もビルドに含めないように、別途ビルドスクリプトを作成しています。

さいごに

DeployGateとTitanium Mobileの組み合わせは、開発をさらに加速できそうですよね!今後は@astronaughtsさんに使い倒してもらいますw