特定のインスタンスタイプのみ起動できるようにIAMポリシーで制限する

インスタンスタイプを指定して起動を制限するIAMポリシーを紹介します。
2021.02.02

こんにちは、鈴木(純)です。

特定のインスタンスだけを起動できるようなポリシーを作成して、ユーザーが高額なインスタンスタイプを使用しないようにしないよう制限していくポリシーを紹介します。

今回はIAMポリシーをユーザーにアタッチして動作を確認していますが、SCPでも同じ記述で制限できますので、OU単位で制限したい場合にも使ってみてください。

特定のインスタンスタイプだけを指定する

たとえば、ユーザーには無料枠のt2.microだけしか使わせたくないよって時。以下のSCPの例で記載されているものと同じです。IAMポリシーでも同じように利用できます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireMicroInstanceType",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringNotEquals":{                   
          "ec2:InstanceType":"t2.micro"
        }
      }
    }
  ]
}

Conditionの条件にStringNotEqualsで特定のインスタンスタイプを指定してあげます。上記のポリシーでは、起動されたインスタンスが指定したインスタンスタイプ(t2.micro)以外だった場合にインスタンスの起動を拒否するという動作になります。

もう少し多めにインスタンスタイプを指定する

t2.microだけじゃなくて、もう少しだけ多めに使わせて上げたい場合。単純に先ほどのポリシーに指定するインスタンスタイプを増やしてあげましょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireInstanceType",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringNotEquals":{                   
          "ec2:InstanceType":[
              "t2.micro",
              "t3.micro",
              "m5.large"
          ]
        }
      }
    }
  ]
}

単純に配列の形でインスタンスタイプを増やしてあげるだけでいいので分かりやすいと思います。

シリーズを指定してインスタンスタイプを制限したい

インスタンスタイプではなくてインスタンスのシリーズ(t2とかt3、m5など)を指定したい場合。

例えばt2シリーズとt3シリーズ以外を起動させたくない場合、今までの例からいくとパッと思いつくのは以下のようなポリシーかと思います。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireInstanceType",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringNotEquals":{                   
          "ec2:InstanceType":[
              "t2.*",
              "t3.*"
          ]
        }
      }
    }
  ]
}

ec2:InstanceTypeで指定する文字列を*を含めて記載する方法です。このポリシーをアタッチしたユーザーでEC2を起動してみます。

インスタンスタイプをt2.micro にします。

その他はデフォルトの状態で進めます。

作成を行うと以下のように作成に失敗したメッセージが表示されてしまいました。

You are not authorized to perform this operation.とエラーが出ており、どうやら権限が足りていないようです。

少し悩みましたが、原因はStringNotEqualsで指定できるのは文字列のみで、どうやらワイルドカード*を使用した指定ができないようでした。(使用できるものについては明記されているが、StringNotEqualsには使用できるとの記載がない)

ワイルドカード*を使った場合でも、問題なく保存できてしまうので気付きにくいです。注意しましょう。

どう記載するべきか

StringNotEqualsではなく、StringNotLikeを使いましょう。StringNotLikeではワイルドカード*が使えます。

値には、複数文字一致のワイルドカード (*) または 1 文字一致のワイルドカード (?) を指定できます。文字列のどこにでも含めることができます。

IAM JSON ポリシーの要素: 条件演算子 - AWS Identity and Access Management

それを踏まえて修正したのがこちらのポリシー。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireInstanceType",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringNotLike":{                 
          "ec2:InstanceType":[
              "t2.*",
              "t3.*"
          ]
        }
      }
    }
  ]
}

StringNotEqualsStringNotLikeに置き換えるだけです。簡単。

ポリシーを編集して保存します。

まったく同じ条件でインスタンスを作成してみると、無事成功しました。

試しにc4.largeを指定して起動してみます。

ちゃんと指定されたシリーズのインスタンスタイプではないので、作成失敗が表示されました。

まとめ

クラウドの利用はお手軽な反面、少し間違うと高額な請求が届くということもあります。必要以上のインスタンスを使わせたくない場合は、ポリシーで適切に制限しておきましょう。

参考情報

サービスコントロールポリシーの例 - AWS Organizations

IAM JSON ポリシーの要素: 条件演算子 - AWS Identity and Access Management