ロールは作ってもらいたいけどユーザは作らせたくない時のIAMポリシー

AWSアカウントを共用などで使っていて、ユーザ払い出しをしたいけれどなんでもできちゃうと困るなぁ、でも権限なさすぎても困るなぁという時があるかと思います。そういうときがあるんです。 今回は
  • 新規ユーザの作成はさせない
  • ロールやポリシーの作成はなるべく自由にさせたい
  • 自分より強い権限を持つユーザやサービスを作り出させない
  • ユーザやグループへのインラインポリシーのアタッチはさせない
といった感じの権限を絞ったポリシーを作っていきます。 結果以下のようなポリシーが出来上がりました。この記事では以下のポリシーを本ポリシーと呼びます。 *本ポリシーで今回の目的が達成できているかの保証は致しません
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PowerUser",
      "Effect": "Allow",
      "NotAction": "iam:*",
      "Resource": "*"
    },
    {
      "Sid": "TheseActionsSupportKindOfReferenceFromIAM",
      "Effect": "Allow",
      "Action": [
        "iam:Get*",
        "iam:List*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ThisActionSupportPassingIAMRoleToAnyServices",
      "Effect": "Allow",
      "Action": [
        "iam:PassRole"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ThisActionSupportServiceLinkedRoles",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ThisActionSupportUsToAttachAndDetachAnyMangedPoliciesAndAnyInlinePoliciesToAnyRoles",
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:AttachRolePolicy",
        "iam:DetachRolePolicy",
        "iam:PutRolePolicy",
        "iam:DeleteRolePolicy",
        "iam:PutRolePermissionsBoundary"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "iam:PermissionsBoundary": "arn:aws:iam::<youraccountid>:policy/<thispolicyname>"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:UpdateRoleDescription",
        "iam:CreatePolicy",
        "iam:DeleteRole",
        "iam:SimulateCustomPolicy",
        "iam:SimulatePrincipalPolicy",
        "iam:TagRole",
        "iam:AddRoleToInstanceProfile",
        "iam:CreateInstanceProfile",
        "iam:DeleteInstanceProfile"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ManageOwnAccessKeys",
      "Effect": "Allow",
      "Action": [
        "iam:CreateAccessKey",
        "iam:DeleteAccessKey",
        "iam:GetAccessKeyLastUsed",
        "iam:GetUser",
        "iam:ListAccessKeys",
        "iam:UpdateAccessKey"
      ],
      "Resource": "arn:aws:iam::*:user/${aws:username}"
    }
  ]
}

PowerUser

IAMのアクション以外は任意のサービスのすべてのアクションがどのリソースに対しても行うことができる設定です。
{
  "Sid": "PowerUser",
  "Effect": "Allow",
  "NotAction": "iam:*",
  "Resource": "*"
}
大体のシチュエーションはこれでカバーできるかと思いますが、CloudFormationなど他AWSサービスと連携するサービスを使う時はロールを渡してあげなくてはなりませんし、IAMのアクションもある程度使えないとまともにAWSが使えないと思います。なのでこのPowerUserにIAMの権限を足していく方向でいきます。 ただ、必要な権限だけ持たせたいけど、ロールやポリシーを自由に作れると権限以上のことができてしまう… そこで、どうやって権限絞っていくのかを1個1個説明していきます。

Permissions Boundary

いきなり今回の核の部分になるのですが、どうやって与えた権限の範囲内でのみ自由にロールやポリシーの作成、アタッチを可能にするかの私の結論は、今回作成するポリシーがPermission Boundaryに設定されたロールしか作成できない、ポリシーをアタッチできないようにすれば良い、です。 Permissions Boundaryとは https://aws.amazon.com/blogs/security/delegate-permission-management-to-developers-using-iam-permissions-boundaries/ 2018年7月にリリースされたIAMの機能で、ロールの権限を管理ポリシーを使って制限することができる、というものです。 ある管理ポリシーをロールのPermissions Boundaryとしてアタッチすると、そのロールにおいて、その管理ポリシーで有効な権限以上のことはできなくなります。 実はロールにPermissions Boundaryを超える権限を持つポリシーをアタッチすることはできますが、いざ実行しようとするとPermission Errorが出るような挙動になっています。
本ポリシーを使ってユーザはロールの作成、ロールへの管理ポリシーのアタッチ、ロールへのインラインポリシーの追加、ロールから管理ポリシーのデタッチ、ロールからインラインポリシーの削除が可能となりますが、その際に対象のロールにPermissions Boundaryとして本ポリシーが設定されていなけれればならない、というポリシーにしています。<thispolicyname>のところは実際に本ポリシーを作成するときに指定する名前に変えます。<youraccountid>のところも自分のIDを入れます。
{
  "Sid": "ThisActionSupportUsToAttachAndDetachParticularMangedPoliciesAndAnyInlinePoliciesToAnyRoles",
  "Effect": "Allow",
  "Action": [
    "iam:CreateRole",
    "iam:AttachRolePolicy",
    "iam:DetachRolePolicy",
    "iam:PutRolePolicy",
    "iam:DeleteRolePolicy",
    "iam:PutRolePermissionsBoundary"
  ],
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "iam:PermissionsBoundary": "arn:aws:iam::<youraccountid>:policy/<thispolicyname>"
    }
  }
},
ちなみにIAMアクションに関連するConditionで使用可能なキーは以下で確認できます。 https://docs.aws.amazon.com/IAM/latest/UserGuide/list_identityandaccessmanagement.html あわせてポリシーの作成等に必要なものを追加します。
 {
  "Effect": "Allow",
  "Action": [
    "iam:UpdateRoleDescription",
    "iam:CreatePolicy",
    "iam:DeleteRole",
    "iam:SimulateCustomPolicy",
    "iam:SimulatePrincipalPolicy",
    "iam:TagRole",
    "iam:AddRoleToInstanceProfile",
    "iam:CreateInstanceProfile",
    "iam:DeleteInstanceProfile",
    "iam:Get*",
    "iam:List*"
    ],
  "Resource": "*"
 }

PassRole

作成したロールをサービスに渡す為にはpassroleのアクションを許可する必要があります。
{
  "Sid": "ThisActionSupportPassingIAMRoleToAnyServices",
  "Effect": "Allow",
  "Action": [
    "iam:PassRole"
  ],
  "Resource": "*"
},

サービスリンクロール

サービスリンクロールを作成する権限もつけておきます。 サービスリンクロールとは名前の通りサービスにリンクされたロールで、サービスに必要なポリシーがAWSによって事前定義されたロールで、このサービスにはどのような操作が必要かな?というのを考えなくても良くなっています。 サービスリンクロールをサービスに渡すためにpassrole権限は必要ありません。 サービスリンクロールはすべてのサービスにまだ対応していませんし、編集ができないため、カスタムポリシーを自分の権限の範囲内で使うための方法を今回考えています。
{
  "Sid": "ThisActionSupportServiceLinkedRoles",
  "Effect": "Allow",
  "Action": [
    "iam:CreateServiceLinkedRole"
  ],
  "Resource": "*"
}

アクセスキー

最後に自身のアクセスキーの発行や有効/無効、削除といったアクセスキー管理の権限もつけます。
{
  "Sid": "ManageOwnAccessKeys",
  "Effect": "Allow",
  "Action": [
    "iam:CreateAccessKey",
    "iam:DeleteAccessKey",
    "iam:GetAccessKeyLastUsed",
    "iam:GetUser",
    "iam:ListAccessKeys",
    "iam:UpdateAccessKey"
  ],
  "Resource": "arn:aws:iam::*:user/${aws:username}"
}

テスト

今回のポリシーをインラインポリシーにつけたユーザでテスト。
$ aws iam create-role --permissions-boundary "arn:aws:iam::************:policy/thisissspolicy" --role-name temprole --profile test --assume-role-policy-document file://sample-trust.json
{
    "Role": {
        "Path": "/",
        "RoleName": "temprole",
       ・・・省略・・・・
}

正常にロールが作れました。 次にPermissions Boundaryを指定しないで作成。
$ aws iam create-role --role-name mijikaiinochi --profile test --assume-role-policy-document file://sample-trust.json<br>
An error occurred (AccessDenied) when calling the CreateRole operation: User: arn:aws:iam::***********:user/iamtest is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::***********:role/mijikaiinochi
正しくDenyされています。

ユーザが自分以上の権限を持つポリシーを作ってサービス(EC2など)にアタッチできるんじゃない?

サービスにはロールとして権限を委任する必要があり、ロールを作成するときにはPermissions Boundaryが必ず設定されている必要があるので大丈夫です。

強いポリシーをアタッチした後にPermissions Bounaryを削除されてしまうんじゃない?

DeleteRolePermissionsBoundaryはできないようにしている為、削除はできません。 putrolepermissionboundaryで既存のpermission boundaryが書き換えようとしても、書き換え後のPermissions Boundaryに本ポリシーが設定されていないとNGなのでできません。

すでに自分より強いロールがあったらそれをサービスに渡したり、AssumeRoleできるんじゃない?

そのロールが特にエンティティを絞っていなければできます。 ただ、そういうロールがあること自体がまずいです。

ユーザやグループにインラインポリシーつければいけるんじゃない?

今回はユーザやグループへのインラインポリシーのアタッチは許可していません。

リソースベースのポリシーを使えばいけちゃんじゃない?

リソースベースポリシーは、アタッチされたリソースへのアクセスを許可するポリシーで、今回はIAM以外のサービスにはフルアクセスできるようにしているので、リソースベースポリシーで特定のリソースへのアクセス権をつけられたしても特に意味はないので問題ありません。 別AWSアカウントからリソースベースポリシー(信頼ポリシーも)つけられたとしてもそこに関しては管理の範囲外なので問題としません。 リソースベースポリシーが使えるサービス一覧 https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html アイデンティティポリシーとリソースポリシーの違い https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_identity-vs-resource.html

AWS Organizations サービスコントロールポリシー (SCP)使えばいいんじゃない?

たしかに… あとで検証します

まとめ

ユーザとかは情シスなど管理側で管理したいけど、検証とかは自由にやってほしいという時にこういうのが必要なんじゃないかと思って作ってみました。 本ポリシーには抜け道がある、もっといい方法がある、といったことがあればぜひ教えてください!!

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です