AWSで権限に関わる機能の名前
意外と多いのでちょっと整理
- User-Based Policy
- Resource-Based Policy
- Role
- Cross-Account Access Using Resource-Based Policies
- Cross-Account API Access Using IAM Roles
User-Based Policy
要するにUserに対してこのユーザーは何の権限を持ってますよってマネジメントコンソールのIAMから設定してるあれです
余りにも当たり前に使うので割愛
Resource-Based Policy
S3、SNS、SQS、OpsWorksでのみサポートされるリソース単位で誰がアクセスを出来ると設定できる機能
下記のようにUser-Basedが指定ユーザーが指定リソースにアクセスできるではなく
指定リソースにアクセスできるユーザーを設定する形で指定できる。
ただ、とても残念な事に上の4つ以外はサポートされていない
これが全てのサービスに存在していれば僕のしたい事は全て終わっていた。
Role
ポリシーとは別に独立した権限管理一覧を持つ役割定義を指す。
勘違いしがちだがUserやGroupとは一切関係なく
DelegationとFederationの定義の為に存在し
内部サービスもしくは外部サービスに対して自身のAWSの権限を渡す際の定義として機能する
Cross-Account Access Using Resource-Based Policies
上記のResource-Based Policyにて自分以外の他のAWSアカウントに対してS3などへのアクセスを権限を付与する事。
Cross-Account API Access Using IAM Roles
広義にはCross-Accountアクセスと纏めて紹介されたり
AssumeRoleと呼ばれたりもしている様だ
ここではDelegateと言う言葉で説明していく
Roleを用いてRoleにて定義されたリソースを同様にRoleにて定義されたAWS Userに対して委任する機能を指す。
Role内のPrincipalにて定義されたAWS Userを信任し、アクセス権限を委任
委任されたUserがSTSにてAssumeRoleを行う事で信任を受け入れ
委任されたユーザーはRoleに定義された権限の範囲で信任元のAWSサービスへAPIアクセスできるアクセスキーとシークレットキーを得る。
つまり、このDelegateはAPIでアクセスを行う際にCross Account Accessと同様に他ユーザーの管理するリソースへのアクセス権限を一時的に発行してくれる訳である。
イメージとしてはLinuxのsudoに近いかもしれない。
Delegate
手順としては
- 委任元が委任用Roleを作成する
- 委任先が委任用RoleにSTSでaccess出来る様にPolicyを設定する
- 委任先がRoleをSTSでAssumeRoleする
- AssumeRoleの結果得られるAcces-KeyとSceret-Key、TokenでAPIにAccessする
委任するServiceのRoleを作成する
委任を行うにはまず、委任元のユーザーから委任するサービスと信任するユーザーを指定してRoleを作成する必要がある
ここでは委任元をPrinceOfDeploy
委任される相手をSebastianとしよう
Account ID | User Name | |
---|---|---|
委任元 | 123456789000 | PrinceOfDeploy |
委任先 | 111222333000 | Sebastian |
- PrinceOfDeployのマネジメントコンソールのIAMにてRole for Cross-Account Accessを選択しProvide access between AWS accounts you ownを選択する。
- Account IDの入力を求められるので信任する相手であるSebastianのAccount ID:[111222333000]を入力する。
- Set Permissionのダイアログに遷移するので委任したい内容のPolicyを入力する。
名前は適当にDeployRoleとでもしておこう
Roleの作成が済むとTrust Relationshipに以下のような内容が格納されているはずである。
{ "Version": "2012-10-17", "Statement": [{ "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::1112223330:root" }, "Action": "sts:AssumeRole" } ] }このままだとrootユーザーに対して信任してしまうので”AWS”: “arn:aws:iam::1112223330:root”を”AWS”: “arn:aws:iam::1112223330:user/Sebastian”に書き換えて以下の様にする
{ "Version": "2012-10-17", "Statement": [{ "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::1112223330:user/Sebastian" }, "Action": "sts:AssumeRole" } ] }ここで注目すべきはPrincipalで示してる内容はそのものズバリ信任先である。
こうして出来上がったRoleはTrust Relationshipの情報とPolicyの情報の二つを持つ構造になる
当然、一つのRoleに対して複数のPolicyを持ったりも出来るので必要ならPolicyを追加して信任者に対して許可する内容を追加しても良い。Roleを受領準備
委任元でRoleの作成が済んだら委任先でRoleの受領準備必要である
何故ならこのままでは委任先であるSebastianからはPrinceOfDeployが作成したRoleにアクセスが出来ないので受取り様がないからだ
そこで委任先のSebastianで以下のようなPolicyをUserに持たせる{ "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::123456789000:role/DeployRole" } ] }Roleを受け取る
先程、委任先のSebastian側でSTSからRoleにaccess出来るようにしたので実際にSTSでRoleを受領する
STSはマネジメントコンソールからは呼び出す事が出来ないのでAPIにて操作を行う必要がある。
何故かAWSはPHPのサンプルだけが除外されまくってるので敢えてPHPで書くassumeRole(array( 'RoleArn' => 'arn:aws:iam::123456789000:role/DeployRole', 'RoleSessionName' => 'DeployAssumeRole', 'DurationSeconds' => 3600, )); $credentials = $result->get('Credentials'); var_dump($credentials); ?>実行すると以下の様な出力が出ると思う
array(4) { ["SessionToken"]=> string(400) "AQoDYXdzEJn//////////wEakAJLNtwojm5H9bmX+P503Cjb6gOj6fjJWotW3UahDkYNefD9mAVKI0nAnb/G4MYn6qU3/V5t7tOFjVGM7Lsh4IqGQ/TrKzcQgxBhSg8aTxIppikWP92HWvAQwR0A7C/vnXsFvyoS8Z9qUcER5dlcYcRCltcs7F9BVMs6Eyt0IzqTxAtUw1JWoKmey48MDpcrzuFpLYRowbVSAz1UKVKvF1VcfRZ+75ukIm58uHkBEJm+inI013ZOQoQXIFeYIsmr3pIjhbK1c4ur6OwDEwMeYh5l4tXdlRAuyAzPCCXhmHw8cr7AsWmljhtqYCknuiKecuzDpWv7QLjtH+6lw2OcUcsoLRP+ZRD1++NuRRruanoigiDt+dCeBQ==" ["SecretAccessKey"]=> string(40) "+upSxMJdbWaTm4bShJaBRpRbVYbx3W4rKbZRavqx" ["Expiration"]=> string(20) "2014-07-27T00:00:00Z" ["AccessKeyId"]=> string(20) "ASIAJZT4FN3V6SAPQRCQ" }これで得られたSessionToken、AccessKey、SecretKeyにてアクセスを行うとRoleにて委任された内容にアクセスが可能となる
Roleでマネジメントコンソールにアクセスする
上記の内容で概ね、Roleを用いたCross Account Accessの動きが理解で来て
取りあえずAPIで彼是出来る~って状態になったと思うだが!!!
だが、しかし!!!そうじゃないんだ!
俺はAPIからアクセスしたいだけじゃないんだ!!!与えられた権限でマネジメントコンソールにアクセスしたいんだ!!
と言うか、何かの権限を誰かに渡すたびにそれを操作するプログラムをAPIで書くのか?
誰しもがそんな事出来るのか?
否!断じて否である!!!
そんな事だれでも出来たらプログラマは廃業しちまうだろ!と言うか、俺はそもそもマネジメントコンソールでアクセスさせる趣旨でこいつを調べ始めたんだよ!
そういう訳で
取得したCredentials情報からマネジメントコンソールにログインしてアクセスする方法~~~
調べたらRuby,PYTHON,JAVAでこれを実現する方法はawsに記載があった。
例によって例の如くかAWSはPHPのサンプルだけが除外されまくってるのでPHPで書く
と言うかAMAZONにはPHP書く人居ないのか?
人が書いた物をそのまま書いてもつまらん!$credentials = $result->get('Credentials'); $strIssuerURL = "https://mysignin.internal.mycompany.com/"; $strConsoleURL = "https://console.aws.amazon.com/sns"; $strSignInURL = "https://signin.aws.amazon.com/federation"; // CredentialsをURLエンコードしたJSONにする $strSessionJson = sprintf( '{"%1$s":"%2$s","%3$s":"%4$s","%5$s":"%6$s"}', 'sessionId' , $credentials['AccessKeyId'], 'sessionKey' , $credentials['SecretAccessKey'], 'sessionToken' , $credentials['SessionToken']); $strEncodedJson = urlencode($strSessionJson); // サインイントークンを取得する $strGetSigninTokenURL = "$strSignInURL?Action=getSigninToken&SessionType=json&Session=$strEncodedJson"; $htmlSigninToken = file_get_contents($strGetSigninTokenURL); $arySigninToken = json_decode($htmlSigninToken , true); $strSigninToken = $arySigninToken['SigninToken']; $strEncodedSigninToken = urlencode($strSigninToken); // ログインURLを作成する $strSigninTokenParameter = "&SigninToken=$strEncodedSigninToken"; $strIssuerParameter = "&Issuer=".urlencode($strIssuerURL); $strDestinationParameter = "&Destination=".urlencode($strConsoleURL); $strLoginURL = "$strSignInURL?Action=login$strSigninTokenParameter$strIssuerParameter$strDestinationParameter"; echo $strLoginURL;以上だ!
これを先程のAssumeRoleを行うPHPの後に続けて書くと画面上にログインURLを表示するはずだ
別にサーバープログラムとしてPHPを走らせてるならそのまま取得したURLで画面遷移しても良いだろうそういう訳でこれで求めていたマネジメントコンソールまで辿りつけた訳だ
元記事は、こちら