share facebook facebook2 twitter menu hatena pocket slack

2014.07.18 FRI

IAMとSTS

sebastian

WRITTEN BYsebastian

どうも、Battle Programmer Sebastianです!(言ってみたかっただけ)
awsをプログラムする上で避けては通れないと言うより、必須になるサービスとしてIAMとSTSと言う物があります。
実は僕はこのサービス大好きです。
何で好きかって言うとこいつを通すとawsをプログラマとして好きに弄れるから
インフラと考えると何これってサービス何ですけれどawsを ネットワーク上のハードウェアを全てプログラマブルなリソースとしてみる とても素晴らしいサービスなんです。


IAM

何て俺様な名前だろうとかベタな事は言わないで下さい。
Identity and Managementの略です。
主に何をするものかざっと説明しますと

  • awsにアクセスできるユーザーを管理する。(作成、削除)
  • ユーザーをグループに分けて管理する
  • ユーザーとグループに各種サービスのアクセス権限(ポリシー言います)を与える

と言った感じです。

何だ。ただのユーザー管理か・・・・と思うなかれ
そんな事ならプログラマブルがどうこうとか書かないですから

実はまだあります

  • ロールを作成しリソースに対して権限を渡す。

これですこれが大事なんです。
ロール?役割を与えるって事?ユーザーに?と早とちりするなかれ
ロールはEC2に対してロールで指定したawsリソースにアクセスする権限を与える物です

そんなのアクセス権限あるの当たり前だろ?と更なる早とちりをするなかれ

これを設定していると何ができるか?と言うとEC2内で動くPHP,JAVA,Ruby等のアプリケーションに対してプログラム上でawsリソースへのアクセス権限を与えると言う事なのだ

従来は下のソースの様に鍵を指定してインスタンス化してアクセスしていた
基本的にawsのAPIはどの言語であれこれに準じている

S3Client objS3Client = new S3Client::factory(
    array(
        'key' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ,
        'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    )
);

ここでロールをEC2に割り当てるとEC2上でAPIアクセスしているプログラムはこの様になる

S3Client objS3Client = new S3Client::factory();

これで、EC2上のPHPでS3にアクセスしてs3内のファイル一覧を取得してJavaScriptを使用してWebでリッチな管理画面をこさえたり
CloudWatchにアクセスして監視対象のデータを独自の画面で表示したりが秘密鍵漏れるとか気にせずに出来る訳だ

つまり プログラマ的に楽しい!!


STS

IAMは分かった。
でも

  • 俺は自分のWindowsから安全にS3にアクセスしたんだよ!
  • EC2に自分でREST作って経由するとかしか方法ないの?
  • スマフォから安全にDynamoDBを読み書きしたい!

Oh~~
わかる!分かるよ、その気持ち!
秘密鍵をソースコードに埋め込んじゃ危ないしかと言って秘密鍵無いとAPIは外からawsにアクセス出来ないし・・・

そう言う時はSTSを使う
STSって何?と言うとSecurity Token Serviceの略だそうだ

フェデレーション

このSTSの機能としてフェデレーションと言う機能がある

何をする物かと言うと

有効期間(Duration time)を決めて一時的に限定的な認証情報を発行しちゃおうってお話
下の図を見てくれ
awsのサイトに乗ってる奴だ
01

  1. 俺が書いたアプリケーションはIdentityBrokerって奴にアクセスしてる
  2. Identity Brokerって奴が認証してる。でもawsじゃない
  3. 2で認証OKだったらIdentity Brokerって奴がawsのSTSにアクセスしてSTSが一時的な認証情報を発行してる。
  4. 受け取った認証情報使ってEC2とかS3にアクセス

って流れだ
唐突に出て来たIdentity Brokerってのが何だそれ?と思うかも知れない
唐突にawsで無い場所で認証してるが何だこれ?と思うかも知れない
そんな君はとても正しい

思ってくれないと話が進まないから(笑)
Identity Brokerは名前の通りIdentity(身元確認)をBroker(仲介する)役割を持ったプログラムだ
つまり認証は他でやって上手く認証出来たらawsに仲介しますよ~~ってプログラムなわけだ
だから2でawsでない他の認証にアクセスしてるんです
この認証は例えばActive Drectoryだったり例えばLDAPだったりで良い
組織の中でアカウント管理していない組織の方が珍しいからそれで認証してawsにアクセス何てのも出来る

まぁ素敵!!
でも、このIdentity Brokerは何を認証して仲介するかは作る人次第なのでサービスとしては余り用意が無い
C#でサンプルコードあるだけですよ

つまり、プログラマが作って良いんです!
ほら?楽しいでしょう?

ちょっとPHPで書いたものを載せて見ます
ここではS3のフルアクセス権限を1時間下さいと指定しています。

①で何かしらユーザー認証します。
②は件のフェデレーションよこせ的なメソッドですね
③はユーザー名、①の認証で使ったユーザー名を渡しています。
④有効期間の指定、3600秒って事で1時間ですね
⑤は一時的に与えるアクセス権限のポリシーをJSONフォーマットのテキストで渡してます。
 ここではちょっと見やすい様に予め、$policyで変数に入れてます。

$sid=randomstatementid' . time();
$policy = "'Statement‘: [
    {
      'Sid': $sid,
      'Action': ‘s3:*‘,
      'Effect': 'Allow',
      'Resource': 'arn:aws:s3:::*',
    }
]"

if ( $UserAuth->login() ) {                                 ①
    $objStsClient = STSClient::factory();
    $result = $objStsClient->getFederationToken(array(      ②
        'Name'            => ’Sebastian’,                   ③
        'DurationSeconds' => 3600,                          ④
        'Policy'          => $policy                        ⑤
    ));
} else {
    // @TODO auth error
}

これだけです。
これで$resultの中には認証情報が入ってきます
dumpするとこの通り

GuzzleServiceResourceModel object {
  structure => null
  data => array(4) (
    [Credentials] => array(4) (
      [SessionToken] => (string) xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      [SecretAccessKey] => (string) xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      [Expiration] => (string) 2014-07-7T15:08:26Z
      [AccessKeyId] => (string) xxxxxxxxxxxxxxxxxxxxxx
    )
    [FederatedUser] => array(2) (
      [Arn] => (string) arn:aws:sts::012345678901:federated-user/sebastian
      [FederatedUserId] => (string) 012345678901:sebastian
    )
    [PackedPolicySize] => (string) 13
    [ResponseMetadata] => array(1) (
      [RequestId] => (string) xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx
    )
  )
}

これで怖がることなく認証して色々アクセス出来ます

つまりプログラマ的に楽しい!!


クロスアカウントアクセス

IAMのロールとSTSを使うとアカウントAの権限をアカウントBに委任するなんて事も出来る
実際、余り使わないとは思うので余談的な話になるけれど
awsのページに良い画像があるのでそこからちょいと拝借w

02

  1. アカウントAで委任アクセス権限ロールを作る
  2. ロールに権限付与しとく
  3. アカウントBでからロールくれと要求する
  4. アカウントAのSTSで認証情報を渡す
  5. アカウントBは受け取った認証情報でアクセスしてアカウントAが委任してくれたリソース叩ける

つまり、プログラマ的に楽しい!!

元記事は、こちら

sebastian

sebastian