特定のEC2起動停止専用のIAMユーザー

# はじめに

AWSにて特定のEC2サーバのみを起動停止するだけのユーザーを作ることになりました。

- 対象となるサーバは今後増えることが予想されるため、  
対象かどうかの判定にはインスタンスIDではなくタグを用いて判別しています。
- そのユーザーのアクセス元IPは固定IPであることから、  
そのフィルタも入れることでセキュリティを向上させています。
- ほかのEC2サーバの詳細な情報はそのユーザーには知られたくないため、  
AWSCLIからのみのアクセスとします。

# 作業
それでは実際に設定してみます。
ポリシーを作ってIAMユーザーに割り当て、
そのIAMユーザーのアクセスキーを使ってCLIで起動停止コマンドを発行する。
という流れです。

## 設定（ポリシー編）
IAM > ポリシー > ポリシーの作成 からポリシーを作ります。
ここでは`ec2StartStopPolicy`とします。
ポリシーのJSONは以下の通りです。

```JavaScript
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",    // (1)
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": [
                        "xxx.xxx.xxx.xxx/32",
                        "yyy.yyy.yyy.yyy/32"
                    ]
                }
            }
        },
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/タグのキー": "タグの値" // (2)
                }
            }
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ec2:DescribeInstanceStatus",
            "Resource": "*"  // (3)
        }
    ]
}
```

### 説明
- (1) 固定IP許可について  
指定したIP以外からの操作は拒否。という形になります。  
記載例のように複数指定することもできます。
- (2) タグによる操作権限  
付与したタグのキー/値がここで指定したものと一致するEC2サーバだけが起動停止可能になります。
- (3) 起動停止ステータスへの権限管理  
EC2サーバが起動しているのか停止しているのかを知るためのActionがec2:DescribeInstanceStatusになります。  
このActionには制限を加えることができません。

## 設定（ユーザー編）
IAM > ユーザー > ユーザーを追加 からIAMユーザーを作ります。

- ユーザー名  
ここでは `ec2StartStopUser` とします
- アクセスの種類  
`プログラムによるアクセス` にだけチェック
- アクセス許可の設定  
`既存のポリシーを直接アタッチ` を選択し、`ec2StartStopPolicy` を指定

アクセスキーID/シークレットアクセスキーのペアが生成されますのでメモっておきます。

## 設定（CLI編）
Amazonのマニュアルを参考にCLIをインストールして設定します。

- Windows に AWS CLI をインストールする  
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-windows.html
- AWS CLI の設定  
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html

CLIに先ほど作成したec2StartStopUserユーザーのアクセスキーID/シークレットアクセスキーを設定します。
CLIに設定がされたかどうかは`aws configure list`で確認できます。

## EC2構築
適当にEC2インスタンスを起動します。
ポリシーの`"ec2:ResourceTag/タグのキー": "タグの値"`で許可設定したとおりにタグを設定します。
起動したらインスタンスIDをメモっておきます。

## 確認
AWSCLIからコマンドを発行して、期待した設定どおりになっているかを確認します。
使用するコマンドは以下の通りです。

- 確認  
`aws ec2  describe-instance-status --instance-ids [instance-id]`
- 起動  
`aws ec2 start-instances --instance-ids [instance-id]`
- 停止  
`aws ec2 stop-instances --instance-ids [instance-id]`

### 起動前の確認

```
c:\>aws ec2  describe-instance-status --instance-ids i-XXXXXXXXXXXXXXXXX
{
    "InstanceStatuses": []
}
```
起動していないので、何も情報が取れません。
### 起動
```
c:\>aws ec2 start-instances --instance-ids i-XXXXXXXXXXXXXXXXX
{
    "StartingInstances": [
        {
            "CurrentState": {
                "Code": 0,
                "Name": "pending"
            },
            "InstanceId": "i-XXXXXXXXXXXXXXXXX",
            "PreviousState": {
                "Code": 80,
                "Name": "stopped"
            }
        }
    ]
}
```
しばらく待つと起動します。
### 起動後の確認
```
c:\>aws ec2  describe-instance-status --instance-ids i-XXXXXXXXXXXXXXXXX
{
    "InstanceStatuses": [
        {
            "AvailabilityZone": "ap-northeast-1a",
            "InstanceId": "i-XXXXXXXXXXXXXXXXX",
            "InstanceState": {
                "Code": 16,
                "Name": "running"
            },
            "InstanceStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            },
            "SystemStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            }
        }
    ]
}
```
`running`になっていることが確認できます。
### 停止
```
c:\>aws ec2 stop-instances --instance-ids i-XXXXXXXXXXXXXXXXX
{
    "StoppingInstances": [
        {
            "CurrentState": {
                "Code": 64,
                "Name": "stopping"
            },
            "InstanceId": "i-XXXXXXXXXXXXXXXXX",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}
```
しばらく待つと停止します。