はじめに
IAMのPassRole、使ったことありますか?何がなんだかわからない方も、その名前からだいたい想像できると思います。
IAMのPassRoleとはその名のとおりIAMロールをパス(Pass)することです。ただし、このパスの対象は人ではなくAWSのサービスです。
PassRoleによって認証情報をセキュアにAWSサービスに渡すことができますが、一方で丁寧に使用しないとセキュリティリスクに繋がってしまいます。本記事ではそんなIAMのパスロールとセキュリティについて解説したいと思います。
IAMのPassRoleとは
IAMのPassRoleは、IAMポリシーの記述の中で iam:PassRole と表現するアクセス許可です。これは ポリシーがアタッチされているプリンシパル(IAMユーザとIAMロール) が、 AWSのサービス(EC2やLambdaなど) にロールを渡すことを意味しています。これにより、例えばEC2がS3のファイルを読み取れたり、LambdaがDynamoDBにデータを格納することができるようになります。
以下は実際にプリンシパルにiam:PassRole権限を付与した時のポリシーの例です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::123456789123:role/example_role"
]
}
]
}
このポリシーにより、これをアタッチされているエンティティはexample_roleをAWSのサービスのどれかに付与することができるようになります。
"Resource"要素に記載されたIAMロールのみを付与できます
少し簡単に説明してしまいましたが、実際にAWSサービスにIAMロールが渡されるためには以下の3つの条件を満たしている必要があります。
- ロールを渡そうとするプリンシパルは、ポリシー内にiam:PassRole権限を持ち、リソース要素内に渡す必要のあるロールが定義されており、すべてのIAMポリシー内のコンディションが満たされており、SCPなどの他のポリシーで暗黙的または明示的に拒否されていない
- 渡されるロールのロール信頼ポリシーが、渡そうとしているサービスのサービスプリンシパルを信頼している(例として、EC2に渡すロールはEC2のサービスプリンシパル ec2.amazonaws.com を信頼している必要があります)
- 渡されるロールとロールを渡すプリンシパルが両方とも同じAWSアカウント内に存在する
IAMのPassRoleをなぜ意識する必要があるのか
AWSを扱うエンジニアにとってIAMのPassRoleはとても身近なものです。EC2にIAMロールをアタッチしてS3やSystems Managerを操作したり、LambdaにIAMロールをアタッチしてDynamoDBからデータを取り出すなどの例から分かるように、事実上必須だといっても過言ではないと思います。この権限を開発者に割り当てていない組織はほとんどないと思います。
ただし、制限のないPassRoleの許可を与えることはかなり危険です。デフォルトではそのサービスを信頼しているアカウント内の全てのIAMロールを付与できてしまうからです。これにより、AWSサービスを介して意図しない権限昇格を起こすことに繋がりかねません。
以下のようなIAMロールの信頼ポリシーを考えてみましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "example",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789123:root"
},
"Action": "sts:AssumeRole"
}
]
}
このIAMロールは、rootが指定されているのでAWSアカウントを信頼しています。これはアカウント内の全てのAWSサービスも対象に含んでいることを意味します。よって、開発者はこのIAMロールをサービスに付与でき、IAMロールの権限に従ってアカウント内の操作が可能になります。もしこのIAMロールにAdministratorAcceessポリシーが付与されていたりしたら、AWSサービス(例えばEC2)をクラックしてIAM関連の操作を行ったり、無制限にデータを読み取ったり、リソースを作成してビットコイン採掘したりということが起こりえます。様々な条件が重なっている必要があるとはいえ、危険なことがお分かりいただけたと思います。
とはいえ、iam:PassRoleの権限を単純に奪ってしまうと大幅に開発者の利便性を損なってしまいます。(EC2を作成するのに中央のIAM管理チームに都度連絡が必要な運用なんてやってられませんよね...)
次項以降で、運用上の不都合を回避しつつある程度の統制を持たせてPassRoleを許可する方式について説明します。
iam:PassRoleの統制
iam:PassRoleは他のステートメントから独立させる
手軽に始められることの一つは、他のステートメントから独立させることです。何を言っているかというと、以下のポリシーのように他のステートメントとは別のステートメントにiam:PassRoleを記載すべきだということです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "example1",
"Effect": "Allow",
"Action": [
"s3:*",
"lambda:*",
"ec2:*"
],
"Resource": "*"
},
{
"Sid": "example2",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789123:role/hogehoge"
}
]
}
他のステートメントから独立させて"Resource"句を指定することで、渡せるIAMロールを制限することができます。"Condition"句で条件を付け足すこともできます。他のステートメントから独立させることがまずは第一歩です。
IAMのパスを利用して渡せるロールを制限する
あまり知られていない概念かもしれませんが、IAMにはパスという概念があります。ここでいうパスはpathのことで、ファイルパスと同じです。このパスを利用すると、効率よく"iam:PassRole"を整理できるようになります。
以下のポリシーを考えてみます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::123456789123:role/teamA/*"
]
}
]
}
このポリシーを利用すると、"teamA/"のパスの配下に作成されたIAMロールのみをアタッチできるようになります。つまり、Aというチームの人がAWSサービスにロールを渡すためには、teamA/のパスの下にIAMロールを作成する必要があるということです。これによって、例えばセキュリティチームが別の特権的なロールをこのアカウント内に作っていたとしても、Aチームの人はそれを利用できない、という制御ができるようになります。
IAMロールの作成まで許可する場合はPermissionsBoundaryで許可範囲の上限を設定することがベストプラクティスです
IAMパスは、マネジメントコンソールからIAMロールを作成する際には利用できない機能です。AWS CLIなどを利用する必要があります。詳細は以下のブログをご確認ください。
SCPによって特権的なロールを保護する
SCPを利用することで、特権的なロールを保護することができます。以下のSCPを考えてみます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::*:role/centralTeam/*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalTag/team": "centralTeam"
}
}
}
]
}
上記では先ほど説明したIAMのパスを利用しています。このSCPでは"Condition"句によって、プリンシパルがcentralTeamというteamタグを持っている場合に限って、centralTeam配下にあるロールをサービスに渡すことができるようになります。
以上のような方法で、PassRoleの統制が可能になります。
まとめ
本記事ではPassRoleの持つセキュリティリスク、統制の方法について解説しました。PassRoleの統制をうまく使いこなし、セキュアに開発を進めていきましょう!