指定のEC2インスタンスタイプしか起動できないIAMユーザーを作成する

これはクラスメソッドさんのDevelopers.IOに投稿されている(いつもお世話になっております!)「特定インスタンスタイプのEC2インスタンスが起動できないIAMユーザーを作成する」の対となるべく書いたポストです。

どうでも良い付帯情報が多数書かれておりますので、キモだけ知りたい方は下の方へどうぞ。

事の始まり

今年のJAWS-UG沖縄で恒例のサムライチケットを利用した「アカウント渡すから自由に使っていいよ〜」という自由なハンズオン(過去のイベントはこの辺から見られます)は、IAMユーザを配布しているのですが、毎回ほぼフル権限で渡しています。

これは、何も考えずに渡しているわけではなくて、権限を制限して「なんかこれが出来ないんですケド」という質問や無駄な弊害を無くすべく、意識してやっていました。

で、事件は起こります(^^ゞ

2014年10月に開催したCMS祭りというイベントで、いつもの様にIAMアカウントを配布して網元AMIでWordPressを起動しよう〜!というハンズオンを実施したのですが、その際に・・・。

ということで、翌日インスタンスを停止するクリーニング作業をするまで、AWS Marketplace Charges として$68.45がぶっ飛びました(笑)。

デジタルキューブの小賀さんにご報告したところ、どうもこれはMarketplace経由で選択した時のバグっぽい仕様な感じでしたが、まあ確認画面でインスタンスサイズは出ているので、これは文句を言っても仕方ないことですね。。。
(おそらくインスタンスって何?というかたが、そのままポチポチやったんじゃないかと想像してます)

で、まあ仕方ないので次からはインスタンスのサイズを限定したIAMユーザを渡そう、と思い至り、上記の福田さんのポストを参考にこんなポリシーを書きました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1413712254000",
      "Effect": "Deny",
      "Action": [
        "ec2:RunInstances"
      ],
      "Condition": {
        "StringNotEquals": {
          "ec2:InstanceType": [
            "t1.micro",
            "t2.micro"
          ]
        }
      },
      "Resource": [
          "*"
      ]
    }
  ]
}

ポイントはStringNotEqualsでして、プログラマーなら誰しも思うであろう、StringEqualsで「起動できるインスタンスを指定する」のではなくて、StringNotEqualsで「これ以外は起動しちゃやだ」という指定をしたい、というわけですね。

しかし動かない・・・!?

これで万事オッケ〜、Simulate Policyでテストしても問題ないよ!と浮かれていたのですが、実際にこのポリシーを適用したユーザでインスタンスを起動しようとすると、謎のエラーで起動できない・・・ナゼorz

どう頑張っても駄目だったので、AWS Support (Business) に加入して質問を投げてみました(実はこれもまた一悶着あるのですが(汗)。

AWSのビジネスサポートは初期応答1時間以内で、かなり優秀という印象を持っていました。実ビジネスでAWSを利用するには加入必須のサービスと思われます。
で、その優秀なサポートさんに今まであれこれ質問してきたわけですが、、、、実は解決に至るまでに、今までで一番時間がかかったケースになりました(笑)。

1週間位掛かって解決した結論としては、、、

RunInstances するときにはResource 設定しないと駄目だよ!

とのことでした・・・。あ、この件は公開してもいいという許可は取ってありますのでご安心を。
詳細は以下の
"Supported Resource-Level Permissions for Amazon EC2 API Actions"のRunInstancesの項目を参照してください。 
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-supported-iam-actions-resources.html
というわけで、正しいポリシーの設定は
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1413712254000",
      "Effect": "Deny",
      "Action": [
        "ec2:RunInstances"
      ],
      "Condition": {
        "StringNotEquals": {
          "ec2:InstanceType": [
            "t1.micro",
            "t2.micro"
          ]
        }
      },
      "Resource": [
          "arn:aws:ec2:*:アカウント番号:instance/*"
      ]
    }
  ]
}
となります。

オマケ:クレジットのサポート日割り料金未適用について

で、この質問をするのにJAWS-UG沖縄としてビジネスサポートに入ったわけですが(そもそもIAMに関する質問はビジネスサポート以上からしか出来ない)、初月は日割りでコストを請求されます。

西島の持っているAWSサムライ2014のクレジット適用範囲にはビジネスサポートも含まれていたので、普通にさくっと契約してしまったのですが・・・

うおぉこれもAWS Service Charges で請求が来てる!!

この現象もよく分からなかったのでサポートに問い合わせたのですが、
大変わかりづらくなっており、誠に恐縮ですが、
サービス加入時に発生いたします料金は、前払い金にあたるため、
AWSプロモーションクレジットの対象外となります。
という良く分からない日本語でご回答頂き、「まあいいからとにかく払えや」とのことでした・・・(涙)。
というわけで日割りの$41.94をガッツリ請求されましたとさ。。。

で、お伺いを立てました

このままひとり爆死するのはネタとしては面白いのですが、これで一円も懐にはいらない自分としてはどうにも悔しいでは無いですか。ということでクレジットカード会社からの請求金額確定を待って、JAWS-UG沖縄のコアメンバーの皆様にお伺いを立てました。

請求金額
AWS Support(Business) $41.94 * 107.86円 = 4,524円
AWS Marketplace Charges $68.45 * 114.50 = 7,838円
計12,362円
結果、全会一致で「許してやろう」というお言葉を頂き、端数は面倒なので1万2千円をプール金より出金させて頂きました。

JAWS-UG沖縄にご参加いただき、お気持ちをくださった皆様、スポンサーの皆様により救われました。ありがとうございましたm(_ _)m
(収支表は収支の動きがあった際に、集計してFacebookグループのほうにポストしています)

では最後にこの言葉で締めさせていただこうかと思います。

この記事により多くの無駄な血が流れなくなることを祈っております。