AWS Cloud9で外部Credentialを良い感じに使えるようにしておく

## 概要

### AWS Cloud9とは

AWS Cloud9は、AWSアカウントがあれば利用できるWebIDEです。
Remote Peer Programingもできますし、様々な言語に対応しています。
https://aws.amazon.com/jp/cloud9/

料金も他の高機能多言語IDEに比べて高額というわけでもないと思います。
(個人的には思っていたより安い)

### [本題の説明] Cloud9で外部Credentialを安全かつ、使いやすいように設定できるようにしたい

AWSの環境変数やCredentialは良い感じに使うBest practiceが見つかります。
しかし、例えばGithub access_token (以下 GITHUB_TOKEN)などの **外部Credentialを扱うパターン** のBest practiceは、見当たりませんでした。

そこで **AWS SSM (AWS System Manager)** を使った外部Credentialのsetupが自動的に行われるようにしてみました。

- [AWS SSMとは](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/what-is-systems-manager.html)

```
AWS Systems Manager (以前の Amazon EC2 Systems Manager) は、AWS リソース間で運用データおよび自動化タスクを簡単に一元化できる統一されたインターフェースです。
Systems Manager はインフラストラクチャで運用上の問題を検出して解決するための時間を短縮します。
Systems Manager は、インフラストラクチャのパフォーマンスと設定についての完全像を提供し、リソースとアプリケーションの管理を簡素化することで大規模なインフラストラクチャの運用と管理を簡単にします。
```

### 前提

- このような設定は、 [12 factor app](https://12factor.net/ja/config) の設計に見習って、環境変数を利用して設定するようにしています

## [準備] AWS SSM で環境変数にて外部Credentialを登録しておく

まず、AWS　Cloud9でTerminalを起動します。 (Option + T でも開けます)
そこでaws コマンドがすでに利用できる状態ですので、以下のように環境変数で登録をします。

使い方

```
aws ssm put-parameter --name <環境変数> --type SecureString --value <VALUE>
```

- e.g, GITHUB_TOKEN=XXXXXXXXXXXX

```
aws ssm put-parameter --name GITHUB_TOKEN --type SecureString --value XXXXXXXXXXXX
```

- 上記のように例えばGithub access_tokenを登録するのでしたら、事前にpersonal access_tokenを別途取得しておいてください
   - https://github.com/settings/tokens

確認するには以下のコマンドです。

```
aws ssm get-parameter --name <環境変数>
```
   - [補足] 暗号化されていますので、このままでは使えません
     - (decryptするには 下記にあるように `--with-decryption` を指定します)


## init.js を用意する

init.jsは、Cloud9起動時に読み込まれるSetup用のjavascript fileです。
これを使ってAWS SSM経由で外部Credential を取得できるようにします。

init.jsを開くには、以下のCloud9のメニューから開きます。
![AWS_Cloud9_open_init.js.png](https://qiita-image-store.s3.amazonaws.com/0/4326/c65c9163-1798-7e93-d7a4-49238aa4547a.png)

外部Credentialは、上記でAWS SSMにて登録済みなので以下のようにinit.jsを用意します

- 注意点
   - このとき、 Cloud9で使用しているinstance の　`~/.bash_profile` を書き換えます。
     - すでに色々設定されている場合は、以下のsetupProfileのヒアドキュメント内に追記してください。
     - 新規に設定する場合は特に気にしなくて大丈夫です
   - 以下は　環境変数名を　`GITHUB_TOKEN`としています
     - 異なる名前で登録した場合はそれに合わせるようにしてください

```js
// You can access plugins via the 'services' global variable
/*global services, plugin*/

// Warning: Using this initialization script to load third-party plugins by
// using loadPackage into the AWS Cloud9 IDE is currently not officially
// supported. If you attempt to load third-party plugins into the AWS Cloud9
// IDE, you do so at your own risk. Third-party plugins can have full access
// to all of your AWS Cloud9 environments, including their source code, AWS
// credentials if present, and various other settings and files. We cannot
// provide support for using third-party plugins, and we reserve the right to
// disable this functionality at any time.

"use strict";

console.log("begin init script");
var fs = services["fs"];
const writeFilePath = "~/.bash_profile";
const setupProfile = `# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH
source $HOME/.nvm/nvm.sh

# environment variable. (e.g, GITHUB_TOKEN)
export GITHUB_TOKEN=$(aws ssm get-parameter --name GITHUB_TOKEN --query Parameter.Value --output text --with-decryption)
`;

fs.writeFile(writeFilePath, setupProfile, 'utf8',
  function(err, success) {
    if (err) {
      services["dialog.alert"].show(
        "Error",
        "File Write Operation",
        "Could not write file '" + writeFilePath + "'."
      );
    } else {
      services["dialog.alert"].show(
        "Success",
        "File Write Operation",
        "Wrote file '" + writeFilePath + "'."
      );
    }
  }
);
```

上記で、環境変数 GITHUB_TOKEN が設定されます。

### init.js を保存する

Ctrl + Sだと保存できません。
代わりに説明が出てくるのですが、そのとおりに Cmd + Enterで保存してください。
この時点では、 **~/.bash_profile　の再読み込みはされていない** ので、当該Credentialは有効にはなっていませんのでご注意ください。

### Cloud9を再起動してinit.jsの動作を確認する

Cmd+Shift+Rでブラウザをリロードすることで再実行されます
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/settings-init-script.html

### 環境変数が設定されていることを確認する

Cloud9のTerminalから確認してみてください。

e.g,

```
echo $GITHUB_TOKEN
```

## 補足情報

その他も含めて以下にもまとめておきました
https://gist.github.com/k-oguma/b9270508ceab28e7a8967eb121e17244

- `--type SecureString` 指定で、安全に運用ができます
    - 万が一 SSMの環境変数が漏れてもそのままでは利用できません
    - AWS KMSを利用
        - AWS Cloud9にはデフォルトでKMSの鍵を持っていたので、特に何も用意せずにそのまま使えました