自前code-serverにhttpsで接続する

※ 2019-6-10 code-server起動時のオプション指定の方法が間違っていたため、修正しました。

# はじめに
最近、code-serverというvscodeをブラウザで操作するオープンソースのプロジェクトを見つけました。面白そうだったため、早速ローカル環境でお試しで使ってみました。どうやら、httpsでも通信できるようで、公式のドキュメント通り設定してみました。しかし、公式の方法ではchrome(バージョン74)に証明書を登録できませんでした。そこで本記事に、私自身がchromeを使って、coder-serverとhttps通信できるまで行った作業をまとめました。

## 検証した環境
OS　ubuntu18.04LTS
ブラウザ　chrome メジャーバージョン74(2019/6/6 おそらく最新)

# 1. coder-serverで使用する証明書と秘密鍵の作成
## 1.1 オレオレ認証局を作成する
### 必要なファイル・ディレクトリを揃える
認証局を作るには、ファイルやディレクトリを作る必要があります。ごちゃごちゃしないように、認証局用のディレクトリを作ることをおすすめします。認証局用のディレクトリは、作成場所が指定されていないため、自分で管理しやすい場所に作るといいでしょう。

```bash
mkdir certs
# このディレクトリの下に、秘密鍵を保存します
# 必ずアクセス制限（600）をかけてください
mkdir private
mkdir crl
mkdir newcerts

# bashだと、エラーが出るかもしれません
# その場合は、shでやるか、エディタで作成してください
# 私の環境ではそれでうまくいきました
echo 01 > serial
echo 01 > crlnumber

touch index.txt
touch index.txt.attr
```
### configファイルの書き換え
`/etc/ssl/openssl.cnf`　からデフォルトの設定ファイルを、認証局用のディレクトリの一つ上に持ってきます。作る認証局に合わせて、設定を変更をしていきます。ファイル名は自由です。ただし、拡張子 `.cnf`は揃えてください。

```
[ CA_default ]
# 上書き
dir = ./dir_name    # 認証用のディレクトリ名を指定してください

# 上書き
certicicate = $dir/ca.crt  # 証明証の名前は変えてもokです

# 上書き
private_key = $dir/ca.key  # 秘密鍵の名前は変えてもokです

[ v3_ca ]
# 上書き
# 初期値ですでに指定されているかもしれません
basicConstraints = critical,CA:true
```

### 認証局を作成
認証局用のディレクトリの一つ上のディレクトリを作業を行います。証明書作成時に質問が飛んできますが、適当に回答してください。

```bash
# 環境変数を設定しないと, /etc/ssl/openssl.cnf が読み込まれます
export OPENSSL_CONF=<作ったconfigファイルの名前>.cnf

# 秘密鍵の名前は、configに合わせてください
openssl genrsa -out <認証局用のディレクトリ>/private/ca.key　　　　　　　　　　　
openssl req -new -key <認証局用のディレクトリ>/private/ca.key -out <認証局用のディレクトリ>/ca.csr
# 証明書の名前は、configに合わせてください
openssl ca -in <認証局用のディレクトリ>/ca.csr -out <認証局用のディレクトリ>/ca.crt -selfsign -extensions v3_ca
```

## 1.2 オレオレ認証局で署名した証明書と秘密鍵を作成する
### SAN（subjectAltName）を対象サーバに合わせる
chromeに証明書を登録する場合は、SANの指定が必須です。そのため、configでサーバに合わせて、適切なSANを指定する必要があります。先程、作った認証局用のconfigをコピーし、変更を加えていきます。

```
[ user_cert ]
# 追記
subjectAltName = @alt_names

[ req ]
# 上書き
# 初期値ですでに指定されているかもしれません
req_extension = v3_req

[ v3_req ]
# 追記
subjectAltName = @alt_names
# ---- ここまでは確定 ----

[ alt_names ]
# ここをサーバによって、書き分けます
```

項目[ alt_names ]の設定例を示します。例を参考に、サーバに合わせて設定してみてください。

```
# ローカルサーバにアクセスする
DNS.1=localhost

# 192.168.1.2にアクセスする
IP.1=192.168.1.2

# my-server(192.168.3.1)にアクセス(ドメイン、IPに対応）する
DNS.1=my-server
IP.1=192.168.3.1

# 複数のDNS,IPを登録したい
# こんな感じで複数指定できます
DNS.1=~
DNS.2=~
DNS.3=~
IP.1=~
IP.2=~
```

### サーバ用の証明書と秘密鍵を作成する
認証局の作り方とほぼ同じです。

```
# サーバに合わせて作ったconfigを指定してください
export OPENSSL_CONF=<ファイル名>.cnf

openssl Genryaku -out <保存先>.key
openssl req -new -key <上で作った秘密鍵を指定> -out <保存先>.csr
# 認証局が署名してくれるため、-selfsignはいらない
openssl ca -in <上で作った署名要求書を指定>.csr -out <保存先>.crt
```

# 2. code-serverに証明書と秘密鍵を適用
オプションを指定してあげるだけです。

```bash
dumb-init code-server --cert <作った証明書> --cert-key <作った秘密鍵> 
```
※ code-serverのインストール方法は[githubのリポジトリ](https://github.com/cdr/code-server)で確認してください。

# 3. https通信してみる
## crt を der に変更する
拡張子 `.crt` の証明書を、拡張子 `.der`のファイルに変換して、クライアント側に渡すことがお作法になっています。お作法に習って、ブラウザに登録する証明書を`.crt`から`.der`に変換します。

```bash
openssl x509 -inform PEM -in <認証局の証明書>.crt -outform DER -out <任意の名前>.der
```

## chromeに登録する
作ったオレオレ認証局をrootの認証局として、chromeに登録します。こうすることで、オレオレ認証局が署名した証明書が有効になります。登録手順を示します。「設定」　→　「詳細設定」　→　「証明書の管理」　→　「認証局」　→　「インポート」でローカルファイルの選択画面が出ます。先程、変換した `.der`のファイルを選択してください。

## アクセス確認
ここまでくれば、https通信ができるようになっているはずです。デフォルトのポートは8443です。アクセスして、確認してみましょう。まだ問題があった場合は、SANの値が正しく指定されていないことが多いです。configファイルをもう一度確認してみましょう。

# 参考資料
先人様たちに感謝を

[Chrome58以降でハネられないSHA-2でオレオレ認証局署名のあるオレオレ証明書](https://qiita.com/mkgask/items/8d66dcada58a485e3585
)
最終アクセス日 2019/6/6
[ubuntu18.04LTSでOpenSSLを使ったプライベート認証局&証明書を作る](http://idwonder21.hatenablog.com/entry/2019/03/03/123510
)
最終アクセス日 2019/6/6