EC2で特定のインスタンスタイプのみ起動できるIAMポリシーを作る

開発を行っていて、テストインスタンスを立てる事が増えたが、よほどのことがなければt2.microやt3.microしか使わない。

同じように、とりあえずで検証用には特定タイプしか作らない人も多いのではないだろうか。

そんなときに、操作ミスや記述ミスにより間違ってでかいインスタンスを立ててしまわないか心配・・・そんなときに。

ポリシーを作成して、権限を制限してあげましょう。

IAMポリシーの記述方法に関して

まず、書き方として、操作に対して許可文と拒否文を記述していくことになる。

この記述に関しての判断は、

拒否文があるか→許可文があるか→なにも無い場合のデフォルト拒否

の順に判定される。そのため、以下のような権限付与はだめだった。

"Statement": [
        {
            "Action": "ec2:*",
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": "ec2:RunInstances",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:RunInstances",
            "Condition": {
                "StringEquals": {
                    "ec2:InstanceType": "t2.micro"
                }
            },
            "Resource": "*"
        },
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

EC2の操作を全許可、インスタンスの起動を全拒否、t2.microの起動を許可、のようにするとt2.microインスタンスの生成は拒否される。

許可文よりも強くRunInstancesのDenyが優先されるためだ。

上記の記述から拒否分を全体にかけるとどうあがいても拒否されるため、作れないことがわかった。

かといって個別にt2.largeや大量のタイプの拒否文を書くのは面倒だし、そもそも増えた時にそのインスタンスを作れてしまう。

ので、許可文を全体にかけず、ec2:RunInstancesを除く操作を許可して、RunInstancesをデフォルト拒否にし、許可文を書いてロールを作成することにした。

イメージ的にはこんな感じ。

入れるのは、

・EC2以外の拒否

・ec2:RunInstances以外の許可

・ec2:RunInstancesのec2:InstanceType項目があるもの以外の許可

・ec2:RunInstancesのt2.microの許可

これで、t2.micro以外でRunInstancesをしようとした場合にはデフォルト拒否が起きてくれるはず・・・。

EC2他の権限が必要な場合を考えた場合には、「ec2:RunInstances以外の許可」が邪魔になるかもしれないがその時に考えることとする。

ポリシーを作ってみる。

IAMよりポリシーの作成を選択、JSONに以下の記入をします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "NotAction": [
                "ec2:*",
                "autoscaling:*",
                "elasticloadbalancing:*",
                "cloudwatch:*",
                "iam:CreateServiceLinkedRole"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "NotAction": "ec2:RunInstances",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:RunInstances",
            "Condition": {
                "StringNotLike": {
                    "ec2:InstanceType": "*"
                }
            },
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:RunInstances",
            "Condition": {
                "StringEquals": {
                    "ec2:InstanceType": "t2.micro"
                }
            },
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "elasticloadbalancing:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "cloudwatch:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "autoscaling:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:AWSServiceName": [
                        "autoscaling.amazonaws.com",
                        "ec2scheduled.amazonaws.com",
                        "elasticloadbalancing.amazonaws.com",
                        "spot.amazonaws.com",
                        "spotfleet.amazonaws.com"
                    ]
                }
            }
        }
    ]
}

さて、このアカウントから入ってみる。

まずはt2.microがうまく起動できるかどうか。

問題なく作成できました。

今度はmediumで作成

作成前にエラーになりました。

これで望んだ権限が出来上がったので、心配せずに使ってもらえます。

(最後に思ったけど、StringNotLikeをec2:InstanceType=t2.microにしてdenyでも行けたかも知れない・・・?

ec2:InstanceType以外が拒否されるかも知れない。気が向いたら別記事で検証する。)