プライベート認証局を作る

# プライベート認証局を作ろう
最近では通常のコンテンツでもHTTPS利用が当たり前になり、Webサーバを立ち上げる場合はSSL証明書が必要になります。Let's Encryptのような無料で利用できる認証局もあるとはいえ、ホームサーバ用途や開発中のシステムなどでは気軽に証明書を発行できると何かと便利です。というわけで自宅用プライベート認証局を立ち上げてみたので、その手順をまとめます。

この記事を書くにあたっては以下のURLの記事を参考にさせていただきました。
https://pvision.jp/tech/2023/05/web-server-https-support-by-private-ca/

# 認証局用ワークディレクトリの作成
各種のデータ保管用のディレクトリや初期データを作成します。
```
# mkdir -p /etc/pki/CA
# cd /etc/pki/CA
```
場所は基本どこでも良いのですけど、ぼくの場合はこれまでの経緯もあって /etc/pki/CA というディレクトリを作成し、その配下にワークディレクトリを作成しました。
```
# mkdir certs db private
# chmod 700 private
# touch db/index
# openssl rand -hex 16 > db/serial
```

# 認証局用の設定ファイル作成
認証局としてのコマンド実行時に使う設定を記述したファイルを作成します。僕の場合は作業ディレクトリ配下に root-ca.conf という名前、以下の内容で作成しました。
```
name_opt = utf8,esc_ctrl,multiline,lname,align

[req]
default_bits = 4096
encrypt_key = no
default_md = sha256
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = req_dn
req_extensions = req_ext

[req_dn]
countryName = "JP"
organizationName ="Denka's Factory CA"
commonName = "Root CA"

[req_ext]
basicConstraints = critical,CA:true
keyUsage = critical,keyCertSign
subjectKeyIdentifier = hash

[ca]
default_ca = CA_default

[CA_default]
name = root-ca
home = .
database = /etc/pki/CA/db/index
serial = /etc/pki/CA/db/serial
certificate = /etc/pki/CA/$name.crt
private_key = /etc/pki/CA/private/$name.key
RANDFILE = /etc/pki/CA/private/random
new_certs_dir = /etc/pki/CA/certs
unique_subject = no
copy_extensions = none
default_days = 3650
default_md = sha256
policy = policy_match

[policy_match]
countryName = supplied
stateOrProvinceName = optional
organizationName = supplied
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
```
default_daysが認証局の証明書有効期限ですが、ここでは10年（3650日）で設定しました。CA_defaultセクションの諸々のパス設定は、僕の作業ディレクトリ(/etc/pki/CA)に合わせています。

# 認証局のルート証明書を作成
認証局で利用するルート証明書を作成し、自分自身で正規のモノであると署名（いわゆるオレオレ証明書になりますね）します。
```
# openssl req -new -config root-ca.conf -out root-ca.csr -keyout private/root-ca.key
# openssl ca -selfsign -config root-ca.conf -in root-ca.csr -out root-ca.crt -extensions req_ext
```
1行目のコマンドでプライベートキー(root-ca.key)を作成し、同時にCSR(証明書署名要求)(root-ca.csr)を作成しています。ここで作成したCSRに対し、2行目で自己署名しています。

# 署名用のデフォルト設定
CSRに対して署名する際のデフォルト設定ファイルを作成します。僕の場合は作業ディレクトリ配下にsign-server.conf という名前、以下の内容で作成しました。
```
name_opt = utf8,esc_ctrl,multiline,lname,align

[ca]
default_ca = CA_default

[CA_default]
name = root-ca
home = .
database = /etc/pki/CA/db/index
serial = /etc/pki/CA/db/serial
certificate = /etc/pki/CA/$name.crt
private_key = /etc/pki/CA/private/$name.key
RANDFILE = /etc/pki/CA/private/random
new_certs_dir = /etc/pki/CA/certs
unique_subject = no
copy_extensions = copy
default_days = 365
default_md = sha256
policy = policy_match

[policy_match]
countryName = supplied
stateOrProvinceName = optional
organizationName = supplied
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[server_ext]
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:false
extendedKeyUsage = serverAuth
keyUsage = critical,digitalSignature,keyEncipherment
subjectKeyIdentifier = hash
```

# 署名してみる
認証局を作っただけではつまらないので、実際に署名してみます。僕の場合、もともとGitLabで利用する証明書を作りたいというきっかけでプライベート認証局を作ったので、GitLabでの例を示します。

## CSR作成
GitLabのインストール時に生成されているプライベートキーを使ってCSRを作成します。
```
# openssl req -new -key "/etc/gitlab/ssl/gitlab.hoge.org.key" -out "/etc/gitlab/ssl/gitlab.hoge.org.csr" -addext "subjectAltName=DNS:gitlab.hoge.org"
```
ここではインストール時のEXTERNAL_URLを gitlab.hoge.org にしていますので適宜読み替えてください。GitLab以外でプライベートキーの作成から実施する場合は、以下のコマンドラインでプライベートキーを生成できます。
```
# openssl genpkey -out web-server.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
```
ここで生成したプライベートキーを先のコマンドラインの -key に指定、-out については適宜パスを指定してください。

# 署名する
以下のコマンドラインで署名します。
```
openssl ca -config sign-server.conf -in /etc/gitlab/ssl/gitlab.hoge.org.csr -out /etc/gitlab/ssl/gitlab.hoge.org.crt -extensions server_ext
```
-in で指定するのは先に作ったCSRファイル、-outで指定するのが署名済み証明書のファイルです。-configでは先に作ってデフォルト設定ファイルを指定しています。GitLabでは/etc/gitlab/ssl配下にEXTERNAL_URLで指定したURLをファイル名としたプライベートキーと署名済み証明書を格納してからGitLabの再起動することで新しい証明書が使われるようになります。
```
gitlab-ctl restart
```

# OSに信頼する認証局として登録する(RedHat)
GitLabにHTTPS接続するにはOS側にプライベート認証局を信頼済み認証局として登録しておく必要があります。先に作った署名済みルート証明書(先の例ではroot-ca.crt)を以下のコマンドラインで登録します。
```
cp /etc/pki/CA/root-ca.crt /etc/pki/ca-trust/source/anchors/root-ca.crt
update-ca-trust
```
1行目で先に作ったルート証明書をOSが指定する所定の場所にコピーしています。2行目で証明書を反映させています。反映前後で対象サイトにcurlを使ってHTTPSでアクセスし、反映前はエラーだったのが反映後はアクセス可能になることのを見ることで動作確認できます。

# OSに信頼する認証局として登録する(Windows)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105734/8e297fd8-d9ee-0666-e99b-59c6d7590187.png)
コントロールパネルの[インターネットオプション]から、コンテンツタブを選択、[証明書]ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105734/96991ae3-0f70-f4c0-9c39-58c81a76edc9.png)
[インポート]ボタンをクリックするとウィザードが起動するので、先に作成したルート証明書(root-ca.crt)を読み込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105734/6849edc9-29c5-cd95-6348-184cd4825efd.png)
証明書ストアは[信頼されたルート証明機関]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105734/c396fccc-4b7b-509e-5598-6f7fae412818.png)
インポートが完了しましたらブラウザで確認してみましょう。