openssl.cnfを改変せずにopensslコマンドでSAN情報を付加した証明書発行要求(CSR)を作成する

\:information_source: この記事は別サイトで執筆した[openssl.cnfを改変せずにopensslコマンドでSAN情報を付加した証明書発行要求(CSR)を作成する – ひつじぶどう](https://blog.rumraisin.tokyo/?p=135)の内容を転載しています。
# はじめに
どうも‪‪✋(´･ᴗ･\` )‬
opensslコマンドでSAN情報を付加したCSRを発行したくなったのですが, ググっても `openssl.cnf` をいじる方法ばかり出てきて苦戦したので忘備録です。
複数のサーバーに対するCSRを手元のMacで作って認証局に投げたいので, それでは困るんです。
ちなみに `openssl.cnf` はLinuxだと `/etc/pki/tls/openssl.cnf`, macOSだと `/System/Library/OpenSSL/openssl.cnf` にあるようです。

# SAN情報を付加したくなるケース
いろいろあると思うんですが, DNSにCNAMEを設定していて2つのURLから1つのWebページにアクセスできる環境とか, サーバーを冗長化していてユーザーはVIPに振られているURLからWebサイトにアクセスするとかそういうケースで必要になるかと思います。
あとは自己証明書を使っている場合, DNS情報の記載がないとエラーが出るようになっているようですのでその対策とかでしょうか。

# どこに付加するの?
Common NameやCountry等を記録するサブジェクト領域とは別にある, 「SAN(Subject Alter Name)」という拡張領域に付加します。
ここに複数のFQDNを記録することで, サブジェクトのCommon Nameに記載したWebサイト以外の証明書として使用できるようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319289/98c49ec8-c377-03b8-3c91-9fae4aa2f30a.png" width=520px>

# 手順
以下でCSR発行の手順を説明します。

## 実行環境
この記事を執筆した際は下記の環境で実施しています。

| 項目 | 値 |
|:-----|:----- |
| OS | macOS Mojave |
| OS Version | 10.14.5 |
| OpenSSL Version | 2.6.5 |

## 秘密鍵の作成
まずはCSRを作成するための秘密鍵を作成します。
鍵の長さは任意で良いですが, 今回は2048bitで。

```zsh
$ openssl genrsa 2048 > rumraisin.key
```

## 設定ファイルの作成
SANを指定するために設定ファイルを作成し, 証明書に載せたいDNS情報をそこに記述します。
`[ req ]`, `[ req_distinguished_name ]`, `[ req_ext ]`, `[ alt_names ]`各セクションには下記のものを記述します。

| セクション | 説明 |
|:----------|:----------|
| [ req ]   | 証明書発行要求に関する設定を記述するセクションです。|
| [ req_distinguished_name ] | [ req ]のサブセクションで, CN等の要素を対話的に入力する際のメッセージや各要素のデフォルト値を記述します。|
| [ req_ext ] | 証明書発行要求のための拡張情報を記載するセクションです。 |
| [ alt_names ]	| Subject Alter Nameを記述します。 |

設定ファイル(今回は`rumraisin.cnf`)を作成し, 下記の内容を記載します。

```
[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext
[ req_distinguished_name ]
countryName                = Country Name (2 letter code)
stateOrProvinceName        = State or Province Name (full name)
localityName               = Locality Name (e.g, city)
organizationName           = Organization Name (e.g, company)
commonName                 = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = rumraisin.tokyo
DNS.2 = rumraisin.dev
```

`[ req ]`, `[ req_distinguished_name ]`, `[ req_ext ]`の各セクションは必要に応じて変更してください。
`rumraisin.cnf`の作成が終わったら準備は完了です。
下記のコマンドを打ってCSRを作成します。

```zsh
$ openssl req -new -key rumraisin.key -config rumraisin.cnf -out rumraisin.csr
```
対話型が嫌いな方はワンライナーでもできたと思いますが, 私は嫌いではないので対話型で必要な情報を入力しました。

```zsh
$ openssl req -new -key rumraisin.key -config rumraisin.cnf -out rumraisin.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:JP
State or Province Name (full name) []:Kumamoto
Locality Name (e.g, city) []:Fuyuki-shi
Organization Name (e.g, company) []:Raisin Lab.
Common Name (e.g. server FQDN or YOUR name) []:rumraisin.dev
```

念のために中身を確認します。

```zsh
$ openssl req -text -noout -in rumraisin.csr
```

```zsh
$ openssl req -text -noout -in rumraisin.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = JP, ST = Kumamoto, L = Fuyuki-shi, O = Raisin Lab., CN = rumraisin.dev
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
　　　　　　　　　　　　　　　　　　　　　　　︙
```

これで中身が問題なければOKです。

# 参考にしたページ
- [Know about SAN Certificate and How to Create With OpenSSL](https://geekflare.com/san-ssl-certificate/)
- [【OpenSSL】SANでDNS情報を付与した証明書を作成する - かえでBlog](https://kaede.jp/2018/06/10191854.html)
- [SSLサーバ証明書のSANsとは - Qiita](https://qiita.com/kawaz/items/87b521e4e9e919caec55)
- [SANについて教えてください | サポート・お申し込みガイド | GMOグローバルサイン【公式】](https://jp.globalsign.com/support/faq/516.html)
- [Internet X.509 PKI Certificate and CRL Profile](https://www.ipa.go.jp/security/rfc/RFC2459JA.html)
- [[OpenSSL] openssl.cnfの設定項目 - Life with IT](https://l-w-i.net/t/openssl/conf_001.txt)