[Hands-on] I tried to start and stop the AWS Client VPN in the AWS IoT1-Click

**This article is an automatic translation of the article[4ed55f71635edb31c903] below.
https://qiita.com/speaktech/items/4ed55f71635edb31c903**

# That did
The AWS Client VPN was to AWS IoT1-Click-click-start and stop with a double-click (= association, disassociation to the endpoint of the subnet) to like.

![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/4ddcea86-5314-34a1-76cb-4413f6f7ec39.png)
![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/603f4231-9deb-fbae-96fb-d893e094d475.png)


Rates of AWS Client VPN is caused by associating as the bottom of the citation, the subnet to the Client VPN (endpoint).
If it leaves you make the association, since the rates and at night, such as to not time zone use occurs, we have to perform the association of subnets only when you use.

> In the AWS Client VPN, with respect to the number of active client connections,
> And charges of one hour each unit with respect to the number of the associated subnets to Client VPN will occur.
>
> From: [charge of AWS Client VPN] (https://aws.amazon.com/jp/vpn/pricing/#AWS%20Client%20VPN%20%E3%81%AE%E6%96%99%E9 % 87% 91)

# Premise
- as IoT device, [AWS IoT Enterprise button] (https://www.amazon.co.jp/AWS-IoT-%E3%82%A8%E3%83%B3%E3%82%BF%E3%83 % BC% E3% 83% 97% E3% 83% A9% E3% 82% A4% E3% 82% BA% E3% 83% 9C% E3% 82% BF% E3% 83% B3-% E2% 80% 93-% E3% 82% 92% E3% 82% B7% E3% 83% B3% E3% 83% 97% E3% 83% AB% E3% 81% AB% E3% 80% 82/dp/B075FPHHGG/ref = sr_1_1? __ mk_ja_JP =% E3% 82% AB% E3% 82% BF% E3% 82% AB% E3% 83% 8A & keywords = IoT + AWS & qid = 1572172251 & s = amazon-devices & sr = 8-1) is required. This time of eSIM built-in LTE-M [SORACOM LTE-M Button powered by AWS] using the (https://www.amazon.co.jp/SORACOM-LTE-M-Button-powered-AWS/dp/B07L59ZFVF) Did.

- When you release the association of subnets will not be able to VPN connection, because the fee does not occur,"the association = start of AWS Client VPN subnet", has been defined as"disassociation of subnets = AWS Client VPN of Stop".

- setting procedure of AWS Client VPN is omitted because it was carried out by reference to [this article (AWS Client VPN settings Note)] (https://qiita.com/hmatsu47/items/ce0cc8b7f5747dbb3190).
(Set by AWS CLI procedures are grouped. Became very helpful, thank you)

# Environment
- ** IoT devices **

 - SORACOM LTE-M Button powered by AWS
 
- ** client PC **

 - Windows 10 version 1803 (OS build 17,134.829)
 - PowerShell version 5.1.17134.765
 - AWS CLI version 1.16.148
 - Python version 2.7.15
 - pip version 9.0.1
 - OpenVPN version 2.4.7

- ** AWS service **

 - AWS Client VPN
 - AWS IAM
 - AWS Lambda
 - AWS CloudWatch Logs
 - AWS IoT1-Click

# Setup steps

** The coming out variable in the procedure, as in the following example, please set in advance value. **

```PowerShell:設定例
# 1. IAM の Lambda 実行ロール作成用
$Region="ap-northeast-1"
$RoleName="client_vpn_admin_role"

# 2. Client VPN を操作する Lambda 関数作成用
$FunctionName="manage_client_vpn"
$handlerName="manage_client_vpn_function.lambda_handler"
```

## 1. Create a Lambda execution role of IAM
Lambda function requires a roll that has been created in the IAM, roll provides the necessary access rights to perform the function.
Here, you create a role, access privileges required to Lambda function is to run the"Log output to ** Cloudwatch Logs **"and"associated with the subnet for the ** Client VPN endpoint/disassociation **"( attach the policy) to roll.

(In advance, please create a role-policy.json of the following to the current directory to run the AWS CLI.)

```bash
# ロールの作成
aws iam create-role --role-name $RoleName --assume-role-policy-document file://role-policy.json

# ロールの確認
aws iam get-role --role-name $RoleName

# ポリシーのアタッチ
aws iam attach-role-policy --role-name $RoleName --policy-arn "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"

aws iam attach-role-policy --role-name $RoleName --policy-arn "arn:aws:iam::aws:policy/AmazonEC2FullAccess"

# アタッチしたポリシーの確認
aws iam list-attached-role-policies --role-name $RoleName
```



```json:role-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
       {
         "Action": "sts:AssumeRole",
         "Principal": {
           "Service": "lambda.amazonaws.com"
          },
          "Effect": "Allow",
          "Sid": ""
       }
    ]
}
```

## 2. Create a Lambda function
### 2.1 Creating a deployment package
In any directory, create a package to deploy to Lamda.
(Reference: [S3 to Sync by moving the AWSCLI on Lambda] (http://blog.serverworks.co.jp/tech/2019/04/11/lambda-aws-cli/), Lambda in [aws-cli to create a Scheduled Event] (https://qiita.com/chroju/items/aa65fddadbc18a2e717a))

```bash
mkdir lambda-cli

cd lambda-cli

pip install awscli -t .
```

The following Python script (aws, manage_client_vpn_function.py) to lambda-cli directory that was created to place the.

```python:aws
import sys
import awscli.clidriver
 
 
def main():
    return awscli.clidriver.main()
 
 
if __name__ == '__main__':
    result = main()
    sys.exit(result)
```



```python:manage_client_vpn_function.py
import subprocess


def lambda_handler(event, context):
    client_vpn_endpoint_id = "[あなたの Client VPN エンドポイント ID]"
    subnet_id_list = ["あなたの 関連付けるサブネット ID(カンマ区切りで複数記述可)"]
    click_type = event['deviceEvent']['buttonClicked']['clickType']
    if (click_type == "SINGLE"):
        message = "The button is clicked once."
        start_client_vpn(client_vpn_endpoint_id, subnet_id_list)
    elif (click_type == "DOUBLE"):
        message = "The button is double clicked."
        stop_client_vpn(client_vpn_endpoint_id)
    elif (click_type == "LONG"):
        message = "The button is long pressed."
    else:
        message = "click_type is unknown."
    print(message)


def start_client_vpn(client_vpn_endpoint_id, subnet_id_list):
    for subnet_id in subnet_id_list :
        cmd = "python aws ec2 associate-client-vpn-target-network --client-vpn-endpoint-id " + client_vpn_endpoint_id + " --subnet-id " + subnet_id
        result = subprocess.run(
        cmd.split(" "),
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT
        )
        print(result.stdout.decode())


def stop_client_vpn(client_vpn_endpoint_id):
    cmd = "python aws ec2 describe-client-vpn-target-networks --client-vpn-endpoint-id " + client_vpn_endpoint_id + " --query ClientVpnTargetNetworks[].AssociationId --output text"
    result = subprocess.run(
        cmd.split(" "),
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT
    )
    association_id_list = result.stdout.decode().strip().split()
    print("[DEBUG] association_id_list: %s" %  association_id_list)

    for association_id in association_id_list:
        cmd = "python aws ec2 disassociate-client-vpn-target-network --client-vpn-endpoint-id " + client_vpn_endpoint_id + " --association-id " + association_id

        result = subprocess.run(
        cmd.split(" "),
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT
        )
        print(result.stdout.decode())
```

Once you have created a Python script, and ZIP compression of the lambda-cli directory.

### 2.2 Deploying to Lambda

Specify the ZIP file, to create a Lambda function. (If you want to run in bash, please replace the newline character in the"`"→"\")

```bash
# ロール ARN の取得
$RoleArn=$(aws iam get-role --role-name $RoleName --query 'Role.Arn' --output text)

# Lambda 関数の作成
aws lambda create-function `
    --function-name $FunctionName `
    --runtime python3.7 `
    --role $RoleArn `
    --handler $handlerName `
    --timeout 120 `
    --zip-file fileb://lambda-cli.zip `
    --region $Region

# Lambda 関数の確認
aws lambda get-function --function-name $FunctionName

# 補足：Lambda 関数を更新
aws lambda update-function-code `
    --function-name $FunctionName `
    --zip-file fileb://lambda-cli.zip `
    --publish
```

### 2.3 test run of the Lambda function
It is in the GUI may be a test run, but here runs in AWS CLI.

```bash
# Lambda 関数のテスト実行
aws lambda invoke --invocation-type Event `
    --function-name $FunctionName `
    --region $Region `
    --log-type Tail outfile.txt
```

If CloudWatch Logs logs such as: is long as it is output, is OK.

```json:起動
{
"AssociationId": "cvpn-assoc-XXXXXXXXXXXXXXXX",
"Status": {
"Code": "associating"
}
}
The button is clicked once.
```



```json:停止
{
"AssociationId": "cvpn-assoc-XXXXXXXXXXXXXXXX",
"Status": {
"Code": "disassociating"
}
}
The button is double clicked.
```

It is registered in the ## 3. AWS IoT 1-Click

This article [Step 1: Register to AWS IoT 1-Click] (https://dev.soracom.io/jp/start/aws_button_slack/) Please refer to the.


## 4. Create a project of AWS IoT 1-Click

Open the console of AWS IoT 1-Click from the AWS Management Console, will continue to input shown in the following screen shot.

![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/b6f39d30-f7db-e407-4a4c-4aa332a20edc.png)
![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/db92caaf-65d9-3637-c274-3dfefdb1bc48.png)
![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/8097b88a-dfcd-82c7-1e49-caefbd7bb0dd.png)
![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/bbb725e4-4852-2767-0ad9-1542357cb16f.png)
![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/8501a009-7714-d360-e38f-07563a7f303b.png)


Select the device that has been registered, if complete the creation of the placement, configuration is completed.
Try, by clicking on the button of IoT devices, it is passed if it can be confirmed that it has succeeded in Lambda function call from the console of the report of the AWS IoT 1-Click.
Thank you for your hard work.
![Image.png] (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/4919847b-e7dd-a154-b02c-a0e35418158b.png)

# Finally

Previous article [saving surgery! ? In the AWS Client VPN tried to start and stop on time in the Lambda] (https://qiita.com/speaktech/items/a07ff10533cfe55b7936), introduced the method of the association, disassociation of Client VPN endpoint on time .
This time, in conjunction with IoT button that was anxious before, I tried to be able to release associated with associated with,.
It flexibility will listen than the scheduled execution, by clicking the button, good! That Tsu'll develop is recommended because the motivation switch also enter (laughs).

I received read to the end, thank you.