プライベートサブネット内のEC2 (Amazon Linux 2) 上にAWS Cloud9を構築する

# はじめに

Cloud9とは、AWSのマネジメントコンソール上（つまり、ブラウザ上）でコーディングができるソリューションです。
AWSのサーバーレスアーキテクチャとの相性もよく、AWSを利用する上では是非検討したいソリューションです。

こういったソリューションが台頭してくる要因として、クラウドを利用する上での「コーディング環境」が挙げられます。
Vimmerならどこであっても実装に困りませんが、普段ローカルPCのIDE等を利用している開発者がいざクラウドを利用しようとすると、この「コーディング環境」という壁にぶち当たることもあるのではないでしょうか？
また、Cloud9のようなクラウド上で使える魅力的なエディターがあっても、会社のプライバシーポリシー的に導入が難しかったりと次々と壁にぶち当たるのも世の常です。

本記事では、そういった点を踏まえて、できる限りセキュアにCloud9を使うための構築手順とセキュリティ要件をご紹介します。
なお、Cloud9の使い方はご紹介しませんので、ご注意ください。

# 対象読者

次のようなアーキテクチャでCloud9を利用したい方全員
（Cloud9サーバーはプライベートサブネットに置き、踏み台経由でしかアクセスできない）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555899/a7634b49-bfc9-60fb-0400-7484f2c918eb.png" width="60%">

# セキュリティ要件

上の画像では少し語弊というか間違いがあり、マネジメントコンソールでCloud9を開けばローカルPCからSSHするわけではありません。
マネジメントコンソールからCloud9を開くと、AWSを経由して踏み台サーバーにSSH、踏み台サーバーがCloud9サーバーにSSHするという仕組みになっています。
したがって、踏み台サーバーはAWS側に22番TCPポートを解放しておく必要があります。
[AWS Cloud9 のインバウンド SSH IP アドレスの範囲](https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/ip-ranges.html)

許可するIPは、
https://ip-ranges.amazonaws.com/ip-ranges.json
こちらのjson中の`region: "ap-northeast-1"`かつ`service: "CLOUD9"`のIPアドレスです。

# Cloud9環境の構築

## 1. Cloud9用EC2を構築

### 1-1. EC2の起動

EC2の設定は次の点だけ守っていただければ、後は自由にしていただいて構いません。

|設定項目|内容|
|:--:|:--:|
|AMI|Amazon Linux 2|
|サブネット|プライベートサブネット|
|PublicIP|無効|
|セキュリティグループ|踏み台サーバーに設定したセキュリテイグループからのSSH (Port:22) を許可する|

### 1-2. Cloud9用の設定

これから、[AWS Cloud9 SSH 開発環境 ホスト要件](https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/ssh-settings.html#ssh-settings-requirements)を参考に設定をしていきます。
まずは、先ほど起動したCloud9用EC2にSSHします。
SSHしたら、 `yum update` などの普段行う設定を実施してください。
以下は、あくまでもCloud9に必要な設定のみを記載しています。

#### Pythonのインストール

>Python がインストールされている必要があり、バージョンが 2.7 である必要があります。

と記載されているので、Pythonのバージョンを確認します。

```
$ python --version
Python 2.7.16
```

このように2.7系であれば問題ありませんが、もし違えば2.7系を入れてください。
インストール方法は、参考にしている[ホスト要件](https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/ssh-settings.html#ssh-settings-requirements)内に記載されています。

#### Node.jsのインストール

>Node.js がインストールされている必要があり、バージョンが 0.6.16 以降である必要があります。

と記載されているので、Node.jsのバージョンを確認します。

```
$ node --version
-bash: node: コマンドが見つかりません
```

2019年12月23日現在のAmazon Linux 2 AMI (ami-068a6cefc24c301d2)には、標準でNode.jsはインストールされていません。
ここでは、Node.jsのリポジトリをyumリポジトリに追加する方法でインストールを行いたいと思います。

まずは、現在設定済みのリポジトリをlistしてみます。

```
$ ll /etc/yum.repos.d/
合計 8
-rw-r--r-- 1 root root 985 11月  2 08:45 amzn2-core.repo
-rw-r--r-- 1 root root 943 11月 19 07:59 amzn2-extras.repo
```

ここに、 `nodesource-el7.repo` という名前でリポジトリを追加します。

```
$ sudo vim nodesource-el7.repo
```

バージョンは0.6.16以上を指定されているので、基本どのバージョンでもいいですが、今回はバージョン13を指定しています。
pub_13.xの13の箇所がバージョンとなっており、12や11を入れたい場合はその数字を指定すればOKです。
また、`el/7` は、Red Hat Enterprise Linux 7のことです。

```text:nodesource-el7.repo
[nodesource]
name=Node.js Packages for Enterprise Linux 7 - $basearch
baseurl=https://rpm.nodesource.com/pub_13.x/el/7/$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/NODESOURCE-GPG-SIGNING-KEY-EL
```

最終的に、こんな感じになっていればリポジトリの登録完了です。

```
$ ll /etc/yum.repos.d/
合計 12
-rw-r--r-- 1 root root 985 11月  2 08:45 amzn2-core.repo
-rw-r--r-- 1 root root 943 11月 19 07:59 amzn2-extras.repo
-rw-r--r-- 1 root root 235 12月 23 21:01 nodesource-el7.repo
```

そして、`nodesource-el7.repo` にgpgkeyを指定したので、これもホストにダウンロードしておく必要があります。
ダウンロードはcurlコマンドを使用して、https://rpm.nodesource.com/pub/el/ から落としてきます。

```
$ cd /etc/pki/rpm-gpg/
$ sudo curl -sSO https://rpm.nodesource.com/pub/el/NODESOURCE-GPG-SIGNING-KEY-EL
```

それでは準備が整ったので、Node.jsをインストールしましょう

```
$ sudo yum install nodejs
```

インストールが完了したら、次のコマンドでNode.jsのバージョンが返ってくれば正常にインストールできています。

```
$ node --version
v13.5.0
```

#### Cloud9起動元ディレクトリのパーミッションを設定

今回は、ec2-userのHOMEディレクトリを指定します。

```
$ sudo chmod u=rwx,g=rx,o=rx ~
$ ll /home/
合計 0
drwxr-xr-x 3 ec2-user ec2-user 111 12月 23 21:20 ec2-user
```

#### AWS Cloud9のインストール

インストーラーを使用してCloud9をインストールしますが、その前に必要な`gcc`を先にインストールしておきます。

```
$ sudo yum install gcc 
```

gccのインストールが完了したら、`crul`コマンドでCloud9をインストールします（しばらく時間がかかります）。

```
$ curl -L https://raw.githubusercontent.com/c9/install/master/install.sh | bash
```

インストールの最後に `:Done.`が表示されればインストール完了です。

## 2. マネジメントコンソールからCloud9環境の作成を行う

### 2-1. Cloud9の画面を開く

画面を開いたらオレンジ色のボタン `Create environment` をクリックしましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555899/71eda5b2-86bf-d350-53f4-4ead64cd2213.png" width="70%">

### 2-2. 環境名と説明を入力

入力したら、`Next step`をクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555899/f6e1a4c4-3ff3-2639-f3a4-c05853eb9b2c.png" width="70%">

### 2-3. SSHの設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555899/547b5def-1462-ab94-aafc-2c93576dadf2.png" width="70%">

|設定項目|指定内容|
|:-----:|:-----:|
|Environment type|Connect and run in remote server (SSH)|
|SSH server connection||
|User|Cloud9サーバーにSSHするユーザー|
|Host|Cloud9サーバーのプライベートIP|
|Port|SSHに使用するポート|
|Advanced settings||
|Environment path|Cloud9ログイン時のディレクトリ（デフォルトはHOMEディレクトリ）|
|Node.js binary path|Node.jsのバイナリパス|
|SSH jump host|踏み台サーバーへのSSH時に使用するユーザーとIP（形式はUSER@HOST:PORT）|

### 2-4. 最終ステップ

ここまで入力が完了したら、`Copy key to clipboard`をクリックしSSH公開鍵をクリップボードに保存します。
その後、踏み台サーバーとCloud9サーバーの`~/.ssh/authorized_keys`の両方にコピーします。

さらに、[SSH 環境を作成する](https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/create-environment-ssh.html)の15番に

>Netcat をインストールする必要があります

とある通り、踏み台サーバーにはNetcatをインストールしておく必要があります。
踏み台サーバーもRed Hat系の場合、次のコマンドでインストールできます。

```
$ sudo yum install nc
```

ここまで完了すると、`Next step`の実行が正常に行われるはずです。
すると、確認画面が表示されるので、`環境の作成`をクリックします。
しばらくして、Cloud9のコンソールが開かれれば構築完了です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555899/92cbbb6b-fb06-8fc4-8738-f0a717b79510.png" width="80%">

# まとめ

踏み台サーバーを用いてプライベートサブネット内にCloud9サーバーを構築することができました。
しかしながら、踏み台サーバーにAWSからの22番ポートアクセスを許可する必要があり、この点が会社のセキュリティポリシーに引っかかることが多いような気がします。
Lambdaとの相性も良かったりするそうですので、クラウドサービスの拡大に伴って会社のポリシーも柔軟に変わっていけると良いですね。