証明書の準備・発行からHerokuに反映させるまで

証明書の発行に必要なファイルの生成方法から、取得した証明書をHerokuに反映させるまでを一通りまとめてみました。

#申請準備
##ファイルの生成
各SSL発行会社が解説をしてくれていますので、いくつかリンクしておきます。

*  [SSLサーバ証明書FAQ：CSRの生成方法 | SSL・電子証明書ならGMOグローバルサイン](https://jp.globalsign.com/support/ssl/list.php?cat=csr)  
*  [CSRの生成方法 サポート | コモドSSL](http://comodo.jp/support/csr_generation.html)

ここではMacを利用したOpenSSLでの生成を前提としています。

##OpenSSLとは
>OpenSSLとは、インターネット上で標準的に利用される暗号通信プロトコルであるSSLおよびTLSの機能を実装した、オープンソースのライブラリ
>[OpenSSLとは｜オープンSSL - 意味/定義 ： IT用語辞典](http://e-words.jp/w/OpenSSL.html)

広くはSSLを自分で組み込むことも出来るようですが、ここではSSL発行のための秘密鍵、CSRの生成をOpenSSLを利用して行います。

Macにはデフォルトでインストールされているので、特に準備は不要です。
Windowsの場合の場合にはソースのインストールとPathの設定が必要となるようです。
参考: [Windowsでopensslを使う](http://rms-digicert.ne.jp/howto/basis/openssl_on_windows.html)

##秘密鍵の生成
以下のOpenSSLのコマンドにて秘密鍵を生成します。

```
$ openssl genrsa 2048 > key.pem
```

2048、とは、キー長、鍵の長さになります。
たいていのSSL発行会社では、2048bitのキー長が必要になるようですので、2048で生成します。
参考：[RSA 秘密鍵/公開鍵ファイルのフォーマット - bearmini&#39;s blog](http://bearmini.hatenablog.com/entry/2014/02/05/143510)
また、`genrsa`で生成されるファイルのフォーマットはPEM形式となっているので、ファイルの拡張子は、`.pem`などとしておきます。
(`.key`など、なんでもよい）

参考：[opensslでRSA暗号と遊ぶ - ろば電子が詰まっている](http://d.hatena.ne.jp/ozuma/20130510/1368114329)

###パスフレーズ
上記のコマンドで生成したファイルはテキストエディタ等で開くとそのまま中身が表示されてしまいます。
セキュリティの面などから秘密鍵自体を暗号化したい場合は、パスフレーズを利用して暗号化してやることが出来ます。

```
$ openssl genrsa -des3 2048 > key.pem
Generating RSA private key, 2048 bit long modulus
...
Enter pass phrase:
Verifying - Enter pass phrase:
```

先程のコマンドに、`-des3`オプションをつけてやることで暗号化することが出来ます。
(des3アルゴリズムによる暗号化）
`Enter pass phrase`とパスフレーズを聞かれますので任意のフレーズを入力します。入力中は内容が表示されませんので注意して下さい。
確認のために同じフレーズを入力して完了です。

参考：[パスワードとパスフレーズ(前編) | [ bROOM.LOG ! ]](https://blog.rocaz.net/2005/02/184.html)

###パスフレーズの解除
パスフレーズを設定してやることで秘密鍵を暗号化しましたが、実はパスフレーズで暗号化された状態ではHerokuにアップロードすることが出来ません。
ですので、パスフレーズがかかった鍵ファイルの場合は解除してやる必要があります。

```
$ openssl rsa -in key.pem -out unlock_key.pem
Enter pass phrase for server.key:
writing RSA key
```

正しいパスフレーズを入力すると、暗号化が解除された秘密鍵が生成されます。
参考：[opensslで秘密鍵のパスフレーズを解除する方法](http://rms-digicert.ne.jp/howto/basis/decrypt_key.html)

###web上のツール
以下のようなサービスにて生成することも可能です。
作成した秘密鍵は必ずテキストエディタ等で保存して下さい。

[CSR・秘密鍵生成 | ApacheOK。IIS不可。 | すぐに使える便利なWEBツール | Tech-Unlimited](http://tech-unlimited.com/csr.html)

##CSRファイルの生成
次にCSRファイルを生成します。

>CSRとは、サーバ証明書を発行するための署名要求（Certificate Signing Request）です。
グローバルサインでは、提出されたCSRに認証機関としての署名をして、サーバ証明書を発行します。
[[FAQ] CSRについて教えてください。 | SSL・電子証明書ならGMOグローバルサイン](https://jp.globalsign.com/support/faq/65.html)

CSRファイルには、ディスティングイッシュネーム、と呼ばれるそのサイトの運営会社に関わる情報を含める必要があります。
入力が必要な情報は以下になります。
全て英語で入力します。

| 項目名 | 英名 | 必須 | 入力内容例 | 補足 |
| :-- | :-- | :-- | :-- | :--|
| 国 | Country Name | ◯ | JP | 国コードで入力 |
| 都道府県 | State or Province Name | ◯※ | Tokyo | |
| 市区町村 | Locality Name | ※ | Chiyoda-ku | |
| 会社名 | Organization Name | ◯ | tambourine Inc. | 法律上の正式英文名称 | 
| 部署名 | Organizational Unit Name |  |  | 必要なければ未入力 |
| コモンネーム | Common Name | ◯ | www.example.com | SSLを適用するドメイン名 |
| メールアドレス | Email Address |  | (不要) | |
| パスワード | A challenge password | | (不要) | 証明書を破棄する際のパスワード |
| 別の組織名 | An optional company name | | (不要) | |

※一部の証明書では、市区町村と都道府県に、`Not Applicable`と指定しなければいけない場合もあります。
 [City/Location に「Not Applicable」を指定して下さい  | Symantec](https://knowledge.symantec.com/jp/support/ssl-certificates-support/index?vproductcat=V_C_S&vdomain=VERISIGN.JP&page=content&actp=CROSSLINK&id=SO22958&locale=ja_JP&redirected=true)

以下のコマンドにて生成します。
`key.pem`の箇所には生成した秘密鍵を指定します。
秘密鍵にパスフレーズを設定した場合は、指定したパスフレーズの入力が求められます。

```
$ openssl req -new -key key.pem -out server.csr
...
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```

各項目の内容を入力し、生成します。
ファイル名は、`server.csr`としていますが、拡張子含めて特に指定はありません。
こちらも、PEM形式のファイルとなるため、`.pem`という拡張子がついている場合も多いです。

###参考リンク
各社、CSRの作成方法や説明などが詳しく書かれていますので、参考にしてください。

*  [CSRの生成方法｜マニュアル｜サポート｜SSLサーバ証明書 ジオトラスト](https://www.geotrust.co.jp/support/ssl/csr/)
*  [CSR(証明書お申込みデータ)の作成｜サイバートラスト](https://www.cybertrust.ne.jp/sureserver/support/csr.html)
*  [CSRとは | ValueSSL](https://valuessl.net/support/help/csr_ssl.php)
*  [CSR作成Pleskコントロールパネル[新規/更新]](http://ssl-process.com/support/csr/plesk.php)

# 証明書申請
証明書の申請は作成したCSRファイルの中身をコピペで提出する場合が多いようです。
手続きや、どのタイプがいいか、などは反映するサイトによって様々だと思いますので割愛します。

ちなみに、SHA-1での署名アルゴリズムによる証明書は廃止される事が決まっています。
各サイトでも発行自体が出来ないようになっていると思われますが、ご注意下さい。

参考：[SHA-1からSHA-2への移行について│SSL・電子証明書ならGMOグローバルサイン](https://jp.globalsign.com/sha256/)

## 確認
発行された証明書の内容は、以下のツールなどで確認することが出来ます。
[CSR内容確認 | CSRの中身を再確認してミスを防止 | すぐに使える便利なWEBツール | Tech-Unlimited](http://tech-unlimited.com/csrcheck.html)

また、発行された証明書と秘密鍵のペアが正しいものかどうかは、以下の手順で確認することが可能です。
[SSL証明書・秘密鍵・CSRファイルのペア確認方法 - Qiita](http://qiita.com/sumida0713/items/72fcb2b0ab926c906507)

参考：[【用語明解】証明書の申請で登場する各種ファイルの見分け方 | SSL証明書をもっと探しやすく、そして低価格 【 SSLコンシェル 】](http://www.ssl-concier.com/news/topics/164)

# Herokuへの反映
Herokuへ反映するためには以下の手続きとファイルが必要です。

*  SSLのアドオンを導入
*  アップロードするファイル
	*  証明書 + 中間CA証明書
	*  秘密鍵

## Heroku Toolbelt
証明書などはコマンドラインからアップロードします。
そのため、専用のHerokuコマンドが使えるように、Heroku Toolbeltをインストールしてやる必要があります。

[Heroku Toolbelt](https://toolbelt.heroku.com/)

## SSLアドオン
[SSL - Add-ons - Heroku Elements](https://elements.heroku.com/addons/ssl)

Heroku公式のアドオンで、証明書をアップするためにはこちらが必須、となります。
値段は、$20/月、です。

管理画面から追加するか、Heroku tool beltを導入していれば、以下のコマンドからも追加可能です。

```
$ heroku addons:create ssl:endpoint
```

## 中間CA証明書
証明書とは別に、中間CA証明書、というものが必要となります。
これは、個別に発行してもらうものではなく、各社がプランに応じたものを予め用意している場合が多いです。
例えば以下の様な感じです。

[中間CA証明書ダウンロード｜SSLサーバ証明書 ジオトラスト](https://www.geotrust.co.jp/resources/repository/intermediate.html)

取得したファイル内の、`-----BEGIN CERTIFICATE-----`から、`-----END CERTIFICATE-----`までが必要な情報となります。

参考：[SSLサーバ証明書の中間CA証明書集めを自動化した - Qiita](http://qiita.com/kawaz/items/c32c6a8a02546ec76caa)

## PKCS#12形式
作成した環境によっては、PKCS#12形式と呼ばれる、証明書や秘密鍵などが一つに圧縮された形式のファイルとなる場合があります。
拡張子は、`.pfx`となる事が多いようです。
その場合は、Opensslのコマンドを使用することで取り出す事が可能です。
取り出す際に、パスワードで暗号化されている場合は入力が求められます。

[秘密鍵を取り出す]  

```
$ openssl pkcs12 -in sample.pfx -nocerts -nodes -out sample.key
```

`-nocerts`とつけることで、暗号化せずに取り出すことが可能です。
このオプションをつけずに実行すると、暗号化するためのパスフレーズの入力が求められます。

[中間証明書]  

```
$ openssl pkcs12 -in sample.pfx -cacerts -nokeys -out sample.ca-bundle
```

取得したファイル内の、`-----BEGIN CERTIFICATE-----`から、`-----END CERTIFICATE-----`までが必要な情報となります。

###参考
[PKCS #12 ファイルから秘密鍵,証明書,中間CAを取り出す - Qiita](http://qiita.com/cs_sonar/items/f2753ffdebb1c67d5302)
[OpenSSL PKCS#12操作 &mdash; SSLサーバ証明書のクロストラスト](https://crosstrust.co.jp/support/tech_support/install/openssl_pkcs12)
[OpenSSLでpfx形式、PKCS#12形式をPEM形式に変換する：新米システム管理者の覚書](http://system-admin.seesaa.net/article/94984370.html)

## ファイルのアップロード
### 証明書+中間CA証明書
証明書と中間CA証明書を足して一つのファイルにします。
エディタで改行を挟まずそのままコピペすれば問題ありません。
以下のコマンドでも追記してやることが出来ます。

証明書: server.crt
中間CA証明書: server.ca.crt

```
$ cat server.ca.crt >> server.crt
```

`server.crt`に中間CA証明書`server.ca.crt`の内容が追記されます。

###アップロード
前述しました通り、秘密鍵にはパスフレーズがかかっているとアップロード出来ないため、予めパスフレーズを解除しておきます。
これで準備が整ったのでHerokuにアップロードします。

```
$ heroku certs:add server.crt key.pem
. . .
Adding SSL Endpoint to [APP NAME]... done
press-shiseido now served by ehime-9999.herokussl.com
Certificate details:
Common Name(s): www.example.com
Expires At:     2016-01-31 23:59 UTC
Issuer:         /C=JP/ST=TOKYO/L=Chiyoda-ku/O=tambourine Inc./OU=/CN=www.press.shiseido.com
Starts At:      2015-01-01 00:00 UTC
Subject:        /C=JP/ST=TOKYO/L=Chiyoda-ku/O=tambourine Inc./OU=/CN=www.example.com
SSL certificate is verified by a root authority.
```

HerokuではSSLのエンドポイントとして、`ehime-9999.herokussl.com`のように、`都道府県-数字.herokussl.com`というドメインがランダムで割り当てられます。
このURLに直接アクセスしてもエラーが出て何も表示されませんが、それで正しい挙動となります。

設定されたエンドポイントは以下のコマンドでも確認が可能です。

```
$ heroku certs --app APP_NAME
Endpoint                    Common Name(s)                            Expires               Trusted
--------------------------  ----------------------------------------  --------------------  -------
todohuken-9999.herokussl.com  www.example.com                         2017-01-01 23:59 UTC  True
```

あとは、このエンドポイントをCNAMEにてコモンネームで設定したドメインに設定してやれば完了となります。
CNAMEの設定方法などは割愛します。

一部の証明書では、１つの証明書でwwwあり・なし両方に対応しているものもあります。
その場合は、CNAMEでの設定の際にはどちらでも利用することが出来ます。
[「Subject Alternative Names（サブジェクトの別名）」とは何ですか  | GeoTrust](https://knowledge.geotrust.com/jp/support/knowledge-base/index?vproductcat=G&vdomain=GEOTRUST_JP&page=content&id=SO24206&actp=LIST&viewlocale=ja_JP&locale=ja_JP&redirected=true)

#最後に
いつも各工程が曖昧になりそのつど検索をかける、ということを繰り返していましたので参照しやすいようにまとめてみました。
あまり深く理解せずに書いている部分も多いため、（特に用語の使い方など）間違いなどありましたら優しく突っ込んでもえられば幸いです。