AWSのIAMポリシーは概念がたくさん出てくるので、勉強した範囲でまとめ(間違っているかもしれない)
ポリシーの分類
アタッチ対象による分類
- アイデンティティベースポリシー
- ユーザー、グループ、ロールにアタッチするポリシー。
- アタッチ対象がPrincipalになるので、Principalの指定は不要
- リソースベースポリシー
- S3バケットや、SQSキューなどのリソースにアタッチするポリシー
- インラインポリシーでのみ記述で記述できる
- IAMロールの信頼ポリシーもリソースベースポリシーの一種
管理方式による分類
- AWS管理ポリシー
- AWS側でメンテナンスされるポリシー
- 特定のAWSサービスのSourceIPリストなどを含むポリシーなどは、AWS側で更新してくれる
- カスタマ管理ポリシー
- AWS利用者側でポリシーエディタなどで作成したポリシーに名前をつけたもの
- IAMのポリシー一覧に表示される
- インラインポリシー
- カスタマが作成する点はカスタマ管理ポリシーと同様だが、こちらはAWSの各リソースの設定画面で設定する
- IAMのポリシー一覧には表示されない
ポリシーの構造
- Policy: 実質的にStatementの配列
- Statement: 実際の許可、拒否情報
- Sid: Statementの識別子。自由につけて良い
- Effect: Allow または Deny
- Principal: 許可or拒否を受ける主体
- AWS: AWSアカウント、AWSユーザー、AWSロールなど
- Service: AWSの各種サービス(例えばEC2サービスなど)
- Federated:外部認証ユーザー
- Action: "s3:ListAllMyBuckets"などの文字列 または その配列。"*"ですべてのアクションを表す
- Resouce: ARN文字列 または その配列。 ""ですべてのリソースを表す。ARN内にをワイルドカードとして使用可能
- Condition: 特定の条件のとき許可or拒否するときにつける
Statement配下の4つの頭文字を取ってPARCモデルという
サンプルは下記を参照
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html
IAMユーザー
- 許可ポリシー(Permission Policy): このユーザーが何をできるか or できないか。複数指定可
- 許可境界(Permission Boundary):このユーザーができることの上限。詳しくは後述
IAMロール
- 許可ポリシー、許可境界:IAMユーザーと同様
- 信頼ポリシー:このロールを誰が使ってよいか。詳しくは後述
許可境界(Permission Boundary)
- IAMユーザーがあるアクションを行えるかは、許可ポリシーと許可境界の両方に含まれるかで判定される
- これだけだと許可境界がなくても、許可ポリシーの方から、許可境界に含まれないものを削るだけでもよくなってしまう
- 許可境界の本来のユースケースは、IAMユーザーにIAMロールの作成を許しつつ、IAMユーザーが自身の持っている権限を超えたIAMロールを作って、それをEC2やLambdaなどにアタッチすることで権限昇格してしまうことを防ぐこと
概略レベルでは、下記のような手順で使う
- AWSアカウントの管理者は、IAMロールの上限となるポリシーを定義する
- 名前を仮に MyProjectRoleBoundaries とする
- AWSアカウント管理者は、開発用IAMユーザーを作るときに下記のような許可ポリシーを設定する
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
...
"iam:CreateRole",
"iam:UpdateRole*",
...
],
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary":
"arn:aws:iam::123456789012:policy/MyProjectRoleBoundaries"
}
}
},
- 開発用のIAMユーザーは、IAMロールを作成するときに、その境界として MyProjectRoleBoundaries を設定する
- これでIAMユーザーが、作成したIAMロールのどれだけ強力な権限をつけようとも、MyProjectRoleBoundaries が上限となる
- IAMユーザーが、IAMロール作成時に MyProjectRoleBoundariesを境界に設定しない場合は、上記のConditionによりCreateRoleに失敗してしまう。
- 実際にはこれだけでは穴がたくさんあるので、実践ではより精査が必要となる
- 参考
IAMロールの信頼ポリシー
- 概略的な表現をすれば「誰がこのロールを使えるか」になる
- S3へのFull AccessできるロールをEC2にアタッチするケースでは、ロールの信頼ポリシーでは以下のような記述になる
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
- 文字通りの解釈では「EC2サービスに、AssumeRoleを許可する」となる
- EC2インスタンスが、あるロールとして振る舞う場合、以下のような動きをする
- EC2サービス(EC2インスタンスではないことに注意)が、STS(Secure Token Service)からそのロールのアクセスキーIDとシークレットアクセスキーを取得する
- これがAssumeRoleにより許可される
- EC2サービスは取得したアクセスキーIDとシークレットアクセスキーをEC2インスタンスのメタデータにセットする
- EC2インスタンスからAWSのAPIを呼び出す際には、AWS SDKはIMDS(Instance MetaData Service)から自身に設定されたアクセスキーIDとシークレットアクセスキーを取得し、使用する
- EC2サービス(EC2インスタンスではないことに注意)が、STS(Secure Token Service)からそのロールのアクセスキーIDとシークレットアクセスキーを取得する
- PrincipalをIAMユーザーに変えれば、IAMユーザーがIAMロールのアクセスキーIDとシークレットアクセスキーを取得できるようになる
インスタンスメタデータの取得
インスタンスメタデータは、EC2インスタンス内からは、下記のエンドポイントからcurlなどで簡単に取得することができる
$ curl http://169.254.169.254/latest/meta-data/
この169.254.169.254はリンクローカルアドレスで、EC2インスタンス内からのみ利用できる。
このシンプルなhttp呼び出しを使うやり方はIMDSv1という方式で、今後廃止が予定されているので、
以下のようにIMDSv2方式を使うことが推奨されている
IMDSv2方式ではメタデータの取得の前にトークンを手に入れる
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
トークンを取得したら以下のように、自身に割り当てられたロールを確認する
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/
ロール名が分かったら、AccessKeyIdとSecretAccessKeyを取得する
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/ロール名
- 参考
PassRole
許可境界(Permission Boundary)では、IAMユーザーが自身の権限を超えるRoleを作成することを制限ができました。では、すでに強力な権限を持っているRoleが作成済みであった場合、その利用を制限するにはどうすればよいでしょうか。
例えば、以下があったとしましょう。
- EC2Fullアクセス権限を持っているIAMユーザー
- S3Fullアクセス権限を持ったIAMロール(EC2サービスに、AssumeRoleを許可している)
このIAMユーザーが、自身の作成したEC2インスタンスに、S3Fullアクセスのロールを割り当てることはできるでしょうか?答えはEC2Fullアクセスだけでは無理ですが、IAMユーザーに以下の権限を加えれば可能です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:ListInstanceProfiles",
"Resource": "*"
}
]
}
重要なのはiam:PassRoleの部分です。PassRoleはIAMロールをAWSリソースに割り当てる権限です。
「どのRoleを、どのリソースに割り当てるか」といった細かい指定は下記を参照してください。
参考: https://dev.classmethod.jp/articles/restrict-pass-ima-role-with-passrole/