【AWS】VPC内でCloudShellを起動する

## はじめに

:::note warn
本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。
:::

簡単なCLIコマンドの実行やトラブルシュート時にはCloudShellを使うことがあります。  
しかし、パブリックな環境でのCloudShellはインターネットに接続されているため、セキュリティ面で少し不安がありました。ところが昨年のアップデートで、VPC内でもCloudShellが起動できるようになったとのことで、試してみた記事になります。
参考：[Using AWS CloudShell in Amazon VPC](https://docs.aws.amazon.com/cloudshell/latest/userguide/using-cshell-in-vpc.html)

## IAMの設定
VPC内でCloudShellが起動できるようなIAMポリシーを作成します。  
CloudShellへのフルアクセス権限に加えて、CloudShellに紐づけるENI（Elastic Network Interface）を管理するために以下の権限も付与します。

- ec2:DescribeVpcs
- ec2:DescribeSubnets
- ec2:DescribeSecurityGroups
- ec2:DescribeDhcpOptions
- ec2:DescribeNetworkInterfaces
- ec2:CreateTags
- ec2:CreateNetworkInterface
- ec2:CreateNetworkInterfacePermission
- ec2:DeleteNetworkInterface

なお、`ec2:DeleteNetworkInterface` は必須ではありませんが、CloudShell用に作成されたENIをCloudShellの終了時に削除するためには必要となります。（参考：[IAMポリシーの詳細](https://docs.aws.amazon.com/ja_jp/cloudshell/latest/userguide/sec-auth-with-identities.html)）  
以上を踏まえて、`CloudShellFullAccessIncludingVPC` というIAMポリシーを作成します。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudShellOperations",
      "Effect": "Allow",
      "Action": [
        "cloudshell:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowDescribeVPC",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeDhcpOptions",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DescribeSubnets",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowCreateTagWithCloudShellKey",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateTags"
      ],
      "Resource": "arn:aws:ec2:*:*:network-interface/*",
      "Condition": {
        "StringEquals": {
          "ec2:CreateAction": "CreateNetworkInterface"
        },
        "ForAnyValue:StringEquals": {
          "aws:TagKeys": "ManagedByCloudShell"
        }
      }
    },
    {
      "Sid": "AllowCreateNetworkInterfaceWithSubnetsAndSG",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateNetworkInterface"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:subnet/*",
        "arn:aws:ec2:*:*:security-group/*"
      ]
    },
    {
      "Sid": "AllowCreateNetworkInterfaceWithCloudShellTag",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateNetworkInterface"
      ],
      "Resource": "arn:aws:ec2:*:*:network-interface/*",
      "Condition": {
        "ForAnyValue:StringEquals": {
          "aws:TagKeys": "ManagedByCloudShell"
        }
      }
    },
    {
      "Sid": "AllowCreateNetworkInterfacePermissionWithCloudShellTag",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateNetworkInterfacePermission"
      ],
      "Resource": "arn:aws:ec2:*:*:network-interface/*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/ManagedByCloudShell": ""
        }
      }
    },
    {
      "Sid": "AllowDeleteNetworkInterfaceWithCloudShellTag",
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteNetworkInterface"
      ],
      "Resource": "arn:aws:ec2:*:*:network-interface/*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/ManagedByCloudShell": ""
        }
      }
    }
  ]
}
```

なお、上記のIAMポリシーではパブリック環境でもCloudShellが起動できてしまうため、VPC内でのみ起動できるように制限するためのIAMポリシー `DenyCloudShellPublic` を作成します。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyCloudShellNonVpcEnvironments",
      "Action": [
        "cloudshell:CreateEnvironment"
      ],
      "Effect": "Deny",
      "Resource": "*",
      "Condition": {
        "Null": {
          "cloudshell:VpcIds": "true"
        }
      }
    }
  ]
}
```

作成した `CloudShellFullAccessIncludingVPC`, `DenyCloudShellPublic` をユーザにアタッチします。


## CloudShellの起動
検索窓に`CloudShell` と入力し、CloudShellを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571776/e4f9cc2c-4e21-4deb-afac-03d67d5a0dc8.png)


特に何も制限していなければパブリック環境でCloudShellが起動しますが、今回は `DenyCloudShellPublic` によって制限しているためエラーが起きます。
![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571776/50c3ad98-a763-477c-b20b-9dec15ab6a19.png)


`Create a VPC environment` をクリックし、VPC内でCloudShellを起動するVPCやサブネット、セキュリティグループを設定します。  
セキュリティグループではインバウンドルールは設定せず、アウトバウンドルールのみフルオープンにしています。  
通信先を絞る場合は、アウトバウンドルールを絞るようにします。
![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571776/9e7a45d3-3e2c-431c-b80a-e04f0b57a004.png)


`Create` をクリックすると、環境が作成され、VPC内でCloudShellが起動します。
![image-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571776/71bceea2-4045-4c88-92f1-908c187c0fc0.png)


## まとめ
VPC内でCloudShellを起動する方法を試してみました。  
踏み台サーバーを作成せずともVPC内のリソースに気軽にアクセスできたりする等、便利ですので今後も活用していこうと思います。

:::note warn
本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。
:::