just-in-time virtual machine accessをさわってみた

 Azureの[just-in-time virtual machine access](https://blogs.technet.microsoft.com/jpitpro/2018/03/19/just-in-time-vm-access-is-generally-available/)をさわってみました。


# 作業概要

1. Just In Time VM アクセスを設定する
2. アクセス権を要求する
3. AWSでそれっぽいものを作ってみる

# 1. Just In Time VM アクセスを設定する

Azureポータルにログインして[セキュリティーセンター] - [Just In Time VM アクセス]を選択します。

Freeプランの場合は、Standardプランに変更する必要があります。

　<img width="759" alt="1-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/78ef5e5c-af07-8b4c-8ad7-0a4b8e71cf31.png">

Just In Time VM アクセスを設定したいVMを選択します。

　<img width="747" alt="1-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/85c666d8-c1d8-7e0d-65ca-adad1652017a.png">

許可したいポートとCIDRを設定します。

　<img width="518" alt="1-3.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/540a0fe9-26d7-072c-5652-7a2318f84fd1.png">

# 2. アクセス権を要求する

設定したVMを選択します。

　<img width="740" alt="1-4.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/b2549ab3-67e8-3edc-2570-d4fefbfa39c4.png">

オフをオンに切り替え後、[ポートを開く]をクリックしてアクセス権を要求します。

　<img width="755" alt="1-5.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/4a9a2caa-16cb-c724-e113-f7421440ef00.png">

これでsshでログインできるようになります。

# 3. AWSでそれっぽいものをつくってみる

 just-in-time virtual machine accessをちょっとだけ真似て、AWS IoT Buttonをクリックしたら、EC2のsshポートを開けて、ダブルクリックまたは長押ししたらsshポートを閉じる仕組みを作ってみます。

ssh用のセキュリティーグループを作成します。

　<img width="966" alt="3-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/b5b8bbc7-c342-992c-e11b-0a4406101d5e.png">

Lambdaを作成します。

```python
import boto3
import json

print('Loading function')

SECURITY_GROUP_ID = 'ポートを開ける用のセキュリティーグループID'
DEFAULT_SECURITY_GROUP_ID = 'デフォルトのセキュリティーグループID'

ec2client = boto3.client('ec2')
ec2resource = boto3.resource('ec2')


def lambda_handler(event, context):
    # print("Received event: " + json.dumps(event, indent=2))
    click_type = get_clicktype(event)

    if click_type == 'SINGLE':
        change_port('OPEN')
    elif click_type == 'DOUBLE' or click_type == 'LONG':
        change_port('CLOSE')
    else:
        pass


def get_clicktype(event):
    try:
        clicktype = event['deviceEvent']['buttonClicked']['clickType']
    except KeyError as err:
        clicktype = 'other'
    return clicktype


def change_port(action):
    instanceid_list = get_instanceid_list()
    
    for instanceid in instanceid_list:
        instance = ec2resource.Instance(instanceid)
        security_groups = [sg['GroupId'] for sg in instance.security_groups]
        
        if action == 'OPEN' and SECURITY_GROUP_ID not in security_groups:
            security_groups.append(SECURITY_GROUP_ID)
        elif action == 'CLOSE' and SECURITY_GROUP_ID in security_groups:
            security_groups.remove(SECURITY_GROUP_ID)
        
        if security_groups == []:
            security_groups.append(DEFAULT_SECURITY_GROUP_ID)

        instance.modify_attribute(Groups=security_groups)


def get_instanceid_list():
    instanceid_list = []
    
    paginator = ec2client.get_paginator('describe_instances')
    iterator = paginator.paginate(
        Filters=[
            {
                'Name': 'tag:just-in-time',
                'Values': ['true']
            }
        ]
    )
    for item in iterator:
        reservations = item['Reservations']
        for reservation in reservations:
            instances = reservation['Instances']
            for instance in instances:
                instanceid_list.append(instance['InstanceId'])
    
    return instanceid_list
```

AWS IoT1-Clickのコンソールでプロジェクトとテンプレートを作成し、先程作成したLambdaと紐付けます。

<img width="978" alt="3-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/e6cf594e-3b26-d246-f823-d95e4dcf346e.png">


EC2インスタンスのタグに、[just-in-time=true]を設定します。このタグが付いたEC2インスタンスが対象になります。

　<img width="523" alt="3-3.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/28be3d93-adf7-35e8-6ff5-1f9a07bd9410.png">


これで、AWSの特定のタグ[just-in-time=true]が付いたEC2インスタンスに対し、AWS IoTボタンをクリックするとsshログインが許可され、ダブルクリックまたは長押しするとsshログインが拒否される仕組みができました。

# 雑感
-  just-in-time virtual machine accessは有料のSTANDARDプランでないと利用できないのが玉に瑕