概要
sts:Assume Roleは第三者に自分のAWSアカウントのAPI権限を委譲する仕組みです。
ここで言う第三者というのは
のように様々なモノに委譲が可能です。
sts:Assume Role
どういう用途として使える?
具体的にこの仕組みがどういったことに使えるかをざっと挙げてみます。
ポリシー (付与する権限) |
信頼関係 (誰に付与するか) |
どうなるか |
---|---|---|
EC2ReadOnly | EC2 | EC2インスタンスから http://169.254.169.254/latest/meta-data にアクセスが可能 |
PowerUser | IAMユーザ | IAMユーザ自体は権限を持っていなくても、 AssumeRoleでPowerUserの 一時的な権限を取得できる |
S3ReadOnly | 他AWSアカウント | 他AWSアカウントから自分の S3バケットへアクセス可能 |
何がメリット?
sts:Assume Roleは一時的なCredentialsしか発行されないので、
- IAMユーザを作ってアクセスキーを生成する
- S3の公開設定を細々指定する
といった後々セキュリティ的に負の遺産となる部分を避ける事が可能です。
特に前者は
- アクセスキーがどこかしら(コード・Jenkinsなど)に残ってしまう
- 退職者が出たときのキーローテーションが大変
という問題が起きます。IAMロールであればロールを指定するだけで済むのでそれらの問題を発生させません。
また基本的にAWS CLIや各SDKはIAMロールを指定しておけば一時Credentialsの発行を自動で行ってくれるので、発行部分を気にせずそのポリシーの権限で操作する事が可能です。
具体的な信頼関係の設定
ロールの信頼関係の部分を設定することで、第三者に権限を付与することが可能です。
これの中身を見ると
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
とありますが、このPrincipal
という部分が付与したい第三者
に当たります。
今回だとEC2サービスに付与する感じですね。
自アカウントのIAMユーザに付与したい場合
自アカウント123456789010
のIAMユーザalice
に権限を付与したい場合は以下のようにします。
alice
自身には何の権限も付与せず、sts:AssumeRole
経由でのみ一時的な権限を付与してもらうことでセキュアに管理できるようになります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789010:user/alice" }, "Action": "sts:AssumeRole", "Condition": {} } ] }
別アカウントのIAMユーザに付与したい場合
別のAWSアカウント123456789012
のIAMユーザbob
に付与したい場合は以下のようにします。
先の例とほぼ同じですが、アカウントIDやユーザ名が変わってます。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:user/bob" }, "Action": "sts:AssumeRole", "Condition": {} } ] }
と書きます。
他のケース
IAM JSON ポリシーの要素:Principal - AWS Identity and Access Management
に色んなケースが載っているので、利用したいケースに合わせて設定してください。
Assume Roleで一時的なCredentialsを発行
信頼関係を設定したIAMロールの権限が利用できるよう、一時的なCredentialsを発行します。
前提
今回作ったIAMロールが以下とします。
項目 | 値 |
---|---|
アカウントID | 123456789010 |
ポリシー | ReadOnlyAccess |
信頼関係 | 自アカウント123456789010 のIAMユーザalice |
ロール名 | read-only |
今何の権限も持たないalice
ユーザとして、ローカルではこのユーザのアクセスキーでログイン済みとします。
権限を持たないため、そのままであればAPIを使おうとしても
$ aws s3 ls An error occurred (InvalidToken) when calling the ListBuckets operation: The provided token is malformed or otherwise invalid.
このようにエラーが出ます。
発行
以下のように一時Credentialsを発行します。
$ aws sts assume-role \ --role-arn arn:aws:iam::123456789010:role/read-only \ --role-session-name test-session { "Credentials": { "AccessKeyId": "ASIAWDCMQX6BJNMKE5BK", "SecretAccessKey": "6R4wsfwwIGw/JJO3sb3ueV+9dAzB9r4YH2hPHnh+", "SessionToken": "FQoGZXIvYXdzEEoaDPzruozGwoxTYIVP8CLtA7qSQGcpLHFur3c3Ay4x5EpVtIBc380rzNk5SxthnclYHsUM/yQRMpHJ3tfUsOOw00+c9Vc6/PlkAL5acm5ZqkhakZCkhqc0FOR3GfZJ2HoWU8MJqTpxwLOVYMvJDQIzUQ08HuaPZb1Mmlvb/ygMwFzkJPUpW42Wnp3acnuBQtfmjFrlqYD6w2f7UNhuaAx5zEyd7x3N5xp5J4vMfJfRj0ZqWAeJ8u4NRX/cs5uuAIQjfnG8cjNlMfqTrcw4JnYQ6xaxDEif4dlzUGUBqeG7ilWH3e8pZoS1cl7uK8TogZk+XuZmihBCFZU6ADp1bijE2aPhBQ==", "Expiration": "2018-12-30T17:05:24Z" }, "AssumedRoleUser": { "AssumedRoleId": "AROAIFHIZYMC4SVNWVFKI:test-session", "Arn": "arn:aws:sts::123456789010:assumed-role/read-only/test-session" } }
これでReadOnlyAccess
の権限を持った1時間だけ有効なCredentialsが発行されました。
※上記は値をいじったダミー値です
発行したCredentialsでAPIを叩く
以下のように発行したCredentialsを環境変数にセットして
$ export AWS_ACCESS_KEY_ID=ASIAWDCMQX6BJNMKE5BK $ export AWS_SECRET_ACCESS_KEY=6R4wsfwwIGw/JJO3sb3ueV+9dAzB9r4YH2hPHnh+ $ export AWS_SESSION_TOKEN=FQoGZXIvYXdzEEoaDPzruozGwoxTYIVP8CLtA7qSQGcpLHFur3c3Ay4x5EpVtIBc380rzNk5SxthnclYHsUM/yQRMpHJ3tfUsOOw00+c9Vc6/PlkAL5acm5ZqkhakZCkhqc0FOR3GfZJ2HoWU8MJqTpxwLOVYMvJDQIzUQ08HuaPZb1Mmlvb/ygMwFzkJPUpW42Wnp3acnuBQtfmjFrlqYD6w2f7UNhuaAx5zEyd7x3N5xp5J4vMfJfRj0ZqWAeJ8u4NRX/cs5uuAIQjfnG8cjNlMfqTrcw4JnYQ6xaxDEif4dlzUGUBqeG7ilWH3e8pZoS1cl7uK8TogZk+XuZmihBCFZU6ADp1bijE2aPhBQ==
適当なコマンドを叩いてみると
$ aws s3 ls 2018-12-24 17:49:28 assume-role-test-bucket
このように使えるようになります。
期限が切れると
1時間が過ぎると
$ aws s3 ls An error occurred (ExpiredToken) when calling the ListBuckets operation: The provided token has expired.
このように怒られます。
自動的に使えなくなるので安心ですね。
まとめ
当初IAMロールは「アクセスキー発行しなくて済むから便利だなぁ」くらいにしか考えていませんでしたが、信頼関係の仕組みによってクロスアカウントアクセスなども簡単に設定できますし非常に良い機能だと思います。