takashi kono's blog

コーヒーとキーボードと共に何かを記録していくブログ

Root CA と Intermediate CA と Server CRT を学ぶ

目的

ルート認証機関、ルート証明書
中間認証機関、中間証明書
サーバ証明書
辺りが、いまいちよくわからなかったのでめっちゃググったからその結果をまとめる

CA とは

認証局
サーバ証明書などで使う時、基本的にカスケードになっている

Root CA (ルート認証機関) が有り
Intermediate CA (中間認証機関) が有り
通常は、Intermediate CA に署名依頼を出すことで、サーバ証明書などを発行することが出来る

Root CA 自信は自己署名して、自分を証明している
勝手に出来るかと言うとそうではない
Root CA は国際的に決まった審査のもとに認定される

参考

ssl.sakura.ad.jp

イメージ図

認証機関と証明書の関係の図

f:id:takashikono:20220219145052p:plain
root CA, Intermediate CA の 関係?

f:id:takashikono:20220219231032p:plain
server 秘密鍵を作って server 証明書を作るまで

server 証明書が使われるまでのイメージ図

f:id:takashikono:20220219145347p:plain
TLS の仕組み

システム構成図

f:id:takashikono:20220219145442p:plain
検証用構成図

検証

環境

ホストOS Ubuntu Desktop 18.04
ゲストOS LXC Ubuntu 20.04

openssl サブコマンドについて

どうも法則があるようだ
法則を知っていると覚えやすいと思う
認識が間違っていなければいいのだが。。。

openssl rsa # 秘密鍵を作る時
openssl req # csr (証明書署名要求) を作る時
openssl ca  # ca が署名をする時
openssl x509 # 出来上がった証明書を確認したりする時

lxd init

lxd init

は終わっているものとする

lxc でそれぞれインスタンスを作る

list で表示しやすくするため、名前に共通部分を入れる。今回は CA

lxc launch ubuntu:20.04 rootCA
lxc launch ubuntu:20.04 interCA
lxc launch ubuntu:20.04 serverCA

list

$ lxc list *CA
+----------+---------+----------------------+-----------------------------------------------+------------+-----------+
|   NAME   |  STATE  |         IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
+----------+---------+----------------------+-----------------------------------------------+------------+-----------+
| interCA  | RUNNING | 10.164.40.97 (eth0)  | fd42:8e72:4c1e:a0da:216:3eff:fe6d:c60 (eth0)  | PERSISTENT | 0         |
+----------+---------+----------------------+-----------------------------------------------+------------+-----------+
| rootCA   | RUNNING | 10.164.40.130 (eth0) | fd42:8e72:4c1e:a0da:216:3eff:fec4:2be4 (eth0) | PERSISTENT | 0         |
+----------+---------+----------------------+-----------------------------------------------+------------+-----------+
| serverCA | RUNNING | 10.164.40.175 (eth0) | fd42:8e72:4c1e:a0da:216:3eff:fe4a:5692 (eth0) | PERSISTENT | 0         |
+----------+---------+----------------------+-----------------------------------------------+------------+-----------+

Private Root CA を作る

Private Root CA での下準備

コンテナに入る

lxc shell rootCA

ディレクトリを作る

mkdir -p /opt/pki/{rootCA,tmp}/config

log

root@rootCA:~# mkdir -p /opt/pki/{rootCA,tmp}/config
root@rootCA:~# 

openssl.cnf をコピーして編集

cp -iv /etc/ssl/openssl.cnf /opt/pki/tmp/config/openssl_tmp.cnf

openssl_tmp.cnf を編集
38行目までを削除 [ ca ] から下を残す

320 行目から下を削除
[ tsa ] セクションから下は不要

ここまでで一度 openssl_tmp.cnf を上書き保存

cd /opt/pki/tmp/config
vim openssl_tmp.cnf

diff command

diff -uprN /etc/ssl/openssl.cnf /opt/pki/tmp/config/openssl_tmp.cnf

diff output

root@rootCA:/opt/pki/tmp# diff -uprN /etc/ssl/openssl.cnf /opt/pki/tmp/config/openssl_tmp.cnf
--- /etc/ssl/openssl.cnf        2020-04-20 11:53:50.000000000 +0000
+++ /opt/pki/tmp/openssl_tmp.cnf        2022-02-19 06:33:35.074964197 +0000
@@ -1,41 +1,3 @@
-#
-# OpenSSL example configuration file.
-# This is mostly being used for generation of certificate requests.
-#
-
-# Note that you can include other files from the main configuration
-# file using the .include directive.
-#.include filename
-
-# This definition stops the following lines choking if HOME isn't
-# defined.
-HOME                   = .
-
-# Extra OBJECT IDENTIFIER info:
-#oid_file              = $ENV::HOME/.oid
-oid_section            = new_oids
-
-# To use this configuration file with the "-extfile" option of the
-# "openssl x509" utility, name here the section containing the
-# X.509v3 extensions to use:
-# extensions           =
-# (Alternatively, use a configuration file that has only
-# X.509v3 extensions in its main [= default] section.)
-
-[ new_oids ]
-
-# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
-# Add a simple OID like this:
-# testoid1=1.2.3.4
-# Or use config file substitution like this:
-# testoid2=${testoid1}.5.6
-
-# Policies used by the TSA examples.
-tsa_policy1 = 1.2.3.4.1
-tsa_policy2 = 1.2.3.4.5.6
-tsa_policy3 = 1.2.3.4.5.7
-
-####################################################################
 [ ca ]
 default_ca     = CA_default            # The default ca section

@@ -317,34 +279,3 @@ authorityKeyIdentifier=keyid,issuer
 # This really needs to be in place for it to be a proxy certificate.
 proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

-####################################################################
-[ tsa ]
-
-default_tsa = tsa_config1      # the default TSA section
-
-[ tsa_config1 ]
-
-# These are used by the TSA reply generation only.
-dir            = ./demoCA              # TSA root directory
-serial         = $dir/tsaserial        # The current serial number (mandatory)
-crypto_device  = builtin               # OpenSSL engine to use for signing
-signer_cert    = $dir/tsacert.pem      # The TSA signing certificate
-                                       # (optional)
-certs          = $dir/cacert.pem       # Certificate chain to include in reply
-                                       # (optional)
-signer_key     = $dir/private/tsakey.pem # The TSA private key (optional)
-signer_digest  = sha256                        # Signing digest to use. (Optional)
-default_policy = tsa_policy1           # Policy if request did not specify it
-                                       # (optional)
-other_policies = tsa_policy2, tsa_policy3      # acceptable policies (optional)
-digests     = sha1, sha256, sha384, sha512  # Acceptable message digests (mandatory)
-accuracy       = secs:1, millisecs:500, microsecs:100  # (optional)
-clock_precision_digits  = 0    # number of digits after dot. (optional)
-ordering               = yes   # Is ordering defined for timestamps?
-                               # (optional, default: no)
-tsa_name               = yes   # Must the TSA name be included in the reply?
-                               # (optional, default: no)
-ess_cert_id_chain      = no    # Must the ESS cert id chain be included?
-                               # (optional, default: no)
-ess_cert_id_alg                = sha1  # algorithm to compute certificate
-                               # identifier (optional, default: sha1)
root@rootCA:/opt/pki/tmp#

openssl_tmp.cnf を openssl_ca.cnf という名前でコピー

cp -iv /opt/pki/tmp/config/openssl_tmp.cnf \
  /opt/pki/tmp/config/openssl_ca.cnf

openssl_ca.cnf を編集

[ CA_default ] セクション
dir = ./ にする
default_days = 3650 にする (10 年)
実際に業務で行う時は (1年などの短い期間にする)

[ v3_ca ] セクション
# keyUsage = cRLSign, keyCertSign のコメントを外す

diff

diff -uprN openssl_tmp.cnf openssl_ca.cnf

diff output

root@rootCA:/opt/pki/tmp/config# diff -uprN openssl_tmp.cnf openssl_ca.cnf
--- openssl_tmp.cnf     2022-02-19 06:33:35.074964197 +0000
+++ openssl_ca.cnf      2022-02-19 06:44:58.412271426 +0000
@@ -4,7 +4,7 @@ default_ca      = CA_default            # The default c
 ####################################################################
 [ CA_default ]

-dir            = ./demoCA              # Where everything is kept
+dir            = ./                    # Where everything is kept
 certs          = $dir/certs            # Where the issued certs are kept
 crl_dir                = $dir/crl              # Where the issued crl are kept
 database       = $dir/index.txt        # database index file.
@@ -34,7 +34,7 @@ cert_opt      = ca_default            # Certificate fi
 # crlnumber must also be commented out to leave a V1 CRL.
 # crl_extensions       = crl_ext

-default_days   = 365                   # how long to certify for
+default_days   = 3650                  # how long to certify for
 default_crl_days= 30                   # how long before next CRL
 default_md     = default               # use public key default MD
 preserve       = no                    # keep passed DN ordering
@@ -202,7 +202,7 @@ basicConstraints = critical,CA:true
 # Key usage: this is typical for a CA certificate. However since it will
 # prevent it being used as an test self-signed certificate it is best
 # left out by default.
-# keyUsage = cRLSign, keyCertSign
+keyUsage = cRLSign, keyCertSign

 # Some might want this also
 # nsCertType = sslCA, emailCA
root@rootCA:/opt/pki/tmp#

/opt/pki/rootCA/config/ にコピーする

cp -iv /opt/pki/tmp/config/openssl_ca.cnf \
  /opt/pki/rootCA/config/openssl_ca.cnf

log

root@rootCA:/opt/pki/tmp/config# cp -iv /opt/pki/tmp/config/openssl_ca.cnf \
>   /opt/pki/rootCA/config/openssl_ca.cnf
'/opt/pki/tmp/config/openssl_ca.cnf' -> '/opt/pki/rootCA/config/openssl_ca.cnf'
root@rootCA:/opt/pki/tmp/config#

Private Root CA での前準備

cd /opt/pki/rootCA/
mkdir {newcerts,requests}
echo "01" > serial
echo "00" > crlnumber
touch index.txt

Private Root CA の Private Key を作る

openssl genrsa \
  -out rootCA_key.pem \
  -aes256 \
  -passout pass:root_ca_pass_phrase \
  2048

RSA の 2048 bit を利用する
暗号化強度としては、 2030 年までは安全らしい

password は passout オプションでコマンドに入れ込んだ
今回の password は root_ca_pass_phrase とした

Private Root CA の Private Key で CSR を作る

CSR = Certificate Signing Request (証明書署名要求)
組織名を example とする
private key を -key で入力させておく

openssl req -new \
  -subj "/C=JP/ST=Fukuoka/O=example/CN=example Root CA" \
  -out rootCA_csr.pem \
  -key rootCA_key.pem \
  -passin pass:root_ca_pass_phrase

Private Root CA の CSR を自己署名して root CA の証明書を作る

openssl ca \
  -batch \
  -config config/openssl_ca.cnf \
  -extensions v3_ca \
  -in  rootCA_csr.pem \
  -out rootCA_crt.pem \
  -selfsign \
  -keyfile rootCA_key.pem \
  -passin pass:root_ca_pass_phrase

password を passin で渡している

log

root@rootCA:/opt/pki/rootCA# openssl ca \
>   -batch \
>   -config config/openssl_ca.cnf \
>   -extensions v3_ca \
>   -in  rootCA_csr.pem \
>   -out rootCA_crt.pem \
>   -selfsign \
>   -keyfile rootCA_key.pem \
>   -passin pass:root_ca_pass_phrase
Using configuration from config/openssl_ca.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Feb 19 07:06:30 2022 GMT
            Not After : Feb 17 07:06:30 2032 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Fukuoka
            organizationName          = example
            commonName                = example Root CA
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24
            X509v3 Authority Key Identifier:
                keyid:72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24

            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
Certificate is to be certified until Feb 17 07:06:30 2032 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated
root@rootCA:/opt/pki/rootCA#

証明書の中身を見てみる

root@rootCA:/opt/pki/rootCA# cat rootCA_crt.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, ST=Fukuoka, O=example, CN=example Root CA
        Validity
            Not Before: Feb 19 07:06:30 2022 GMT
            Not After : Feb 17 07:06:30 2032 GMT
        Subject: C=JP, ST=Fukuoka, O=example, CN=example Root CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:ac:99:9e:10:7d:63:2d:01:46:2f:10:ab:9d:51:
                    dc:29:b6:d7:be:8c:18:b8:11:12:a5:47:11:1d:6a:
                    46:f8:60:12:db:2d:80:07:a3:28:34:ba:31:91:45:
                    5b:a4:e2:5a:a6:33:2e:90:27:b5:85:7d:42:91:6d:
                    7c:dd:f1:7b:36:d8:c3:8e:87:b4:ed:27:29:09:c8:
                    63:7d:b1:be:a0:14:88:81:e6:33:1d:2d:8b:de:fd:
                    7f:52:48:80:36:ca:ff:b4:d3:a1:4e:ab:e4:4f:32:
                    5a:d3:d1:c6:c3:15:90:d1:02:a2:a2:5e:ec:fd:5a:
                    85:5a:f2:e8:9e:d1:e4:1a:23:f0:8b:af:ec:1e:c1:
                    f7:cb:32:29:93:37:c6:07:83:ea:db:7b:43:8a:57:
                    e9:3a:10:d1:c7:fa:03:e3:e9:14:9c:f9:6b:96:42:
                    fd:4f:99:e3:f0:04:57:08:9e:dd:a1:d2:94:66:13:
                    e0:a5:4a:03:66:9a:0a:48:8a:11:29:ca:af:81:69:
                    04:22:4f:0d:16:0f:30:a4:db:b3:ab:37:57:53:f4:
                    cc:49:06:52:c6:34:f3:f1:e0:07:67:18:96:51:93:
                    3c:fc:d0:32:3d:08:09:8f:91:80:6f:82:05:32:64:
                    fb:86:7f:49:dd:64:8e:95:91:95:bd:51:48:33:af:
                    82:15
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24
            X509v3 Authority Key Identifier:
                keyid:72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24

            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
         5b:f5:c6:d4:49:c4:0a:80:1c:f2:34:50:c6:86:53:84:b3:72:
         ec:25:f3:db:d0:af:e0:87:03:b2:b1:18:dd:ca:a2:f2:4b:f0:
         d7:ad:35:01:c9:84:b2:32:ab:1f:1e:87:51:e9:ea:ba:8e:b0:
         9a:b2:a1:34:8c:bb:b2:0d:9f:08:c4:91:69:4c:a7:48:5c:b4:
         e5:01:2f:c7:4c:e8:7a:cc:e4:94:70:d2:65:64:0f:2b:03:82:
         0b:de:24:31:83:c7:78:d7:ef:a1:09:09:c6:9e:27:85:8c:80:
         2e:85:1e:03:fb:92:e8:e8:a3:89:a2:4a:1c:30:0e:5e:f4:3c:
         3a:54:d8:3b:74:1b:05:40:7f:8d:89:92:7e:3a:cf:d9:bd:d4:
         70:25:8f:79:2d:ba:68:09:b5:b1:14:cb:2b:4a:d6:9b:7e:b0:
         0c:a6:51:45:95:6c:74:56:96:0e:43:bb:61:30:f9:01:df:2e:
         1e:b1:ab:88:7e:15:94:63:db:42:91:ba:c5:96:d8:45:ef:79:
         d7:41:53:fd:88:8c:88:31:0e:8f:fd:8f:0d:53:b7:32:16:d5:
         d7:7a:99:24:f9:ba:10:ad:83:f0:e6:7f:0e:59:09:e0:f1:bf:
         55:23:87:9c:ff:18:f8:fb:d2:ff:9e:f3:0e:7c:5c:12:00:ac:
         4d:7d:65:a6
-----BEGIN CERTIFICATE-----
MIIDcTCCAlmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJKUDEQ
MA4GA1UECAwHRnVrdW9rYTEQMA4GA1UECgwHZXhhbXBsZTEYMBYGA1UEAwwPZXhh
bXBsZSBSb290IENBMB4XDTIyMDIxOTA3MDYzMFoXDTMyMDIxNzA3MDYzMFowSzEL
MAkGA1UEBhMCSlAxEDAOBgNVBAgMB0Z1a3Vva2ExEDAOBgNVBAoMB2V4YW1wbGUx
GDAWBgNVBAMMD2V4YW1wbGUgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAKyZnhB9Yy0BRi8Qq51R3Cm2176MGLgREqVHER1qRvhgEtstgAej
KDS6MZFFW6TiWqYzLpAntYV9QpFtfN3xezbYw46HtO0nKQnIY32xvqAUiIHmMx0t
i979f1JIgDbK/7TToU6r5E8yWtPRxsMVkNECoqJe7P1ahVry6J7R5Boj8Iuv7B7B
98syKZM3xgeD6tt7Q4pX6ToQ0cf6A+PpFJz5a5ZC/U+Z4/AEVwie3aHSlGYT4KVK
A2aaCkiKESnKr4FpBCJPDRYPMKTbs6s3V1P0zEkGUsY08/HgB2cYllGTPPzQMj0I
CY+RgG+CBTJk+4Z/Sd1kjpWRlb1RSDOvghUCAwEAAaNgMF4wHQYDVR0OBBYEFHJk
MSj2g8OPQWsms5k3SuJ7wW0kMB8GA1UdIwQYMBaAFHJkMSj2g8OPQWsms5k3SuJ7
wW0kMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA
A4IBAQBb9cbUScQKgBzyNFDGhlOEs3LsJfPb0K/ghwOysRjdyqLyS/DXrTUByYSy
MqsfHodR6eq6jrCasqE0jLuyDZ8IxJFpTKdIXLTlAS/HTOh6zOSUcNJlZA8rA4IL
3iQxg8d41++hCQnGnieFjIAuhR4D+5Lo6KOJokocMA5e9Dw6VNg7dBsFQH+NiZJ+
Os/ZvdRwJY95LbpoCbWxFMsrStabfrAMplFFlWx0VpYOQ7thMPkB3y4esauIfhWU
Y9tCkbrFlthF73nXQVP9iIyIMQ6P/Y8NU7cyFtXXepkk+boQrYPw5n8OWQng8b9V
I4ec/xj4+9L/nvMOfFwSAKxNfWWm
-----END CERTIFICATE-----
root@rootCA:/opt/pki/rootCA#

余計な文字列を削除する

必要なのは BEGIN CERTIFICATE からしたのみなので。

cp -iv rootCA_crt.pem rootCA_crt_with_pass_phrase.pem
openssl x509 -in rootCA_crt.pem -out rootCA_crt.pem

log

root@rootCA:/opt/pki/rootCA# cp -iv rootCA_crt.pem rootCA_crt_with_pass_phrase.pem
'rootCA_crt.pem' -> 'rootCA_crt_with_pass_phrase.pem'
root@rootCA:/opt/pki/rootCA#
root@rootCA:/opt/pki/rootCA# openssl x509 -in rootCA_crt.pem -out rootCA_crt.pem
root@rootCA:/opt/pki/rootCA#

中身を見てみる

root@rootCA:/opt/pki/rootCA# cat rootCA_crt.pem
-----BEGIN CERTIFICATE-----
MIIDcTCCAlmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJKUDEQ
MA4GA1UECAwHRnVrdW9rYTEQMA4GA1UECgwHZXhhbXBsZTEYMBYGA1UEAwwPZXhh
bXBsZSBSb290IENBMB4XDTIyMDIxOTA3MDYzMFoXDTMyMDIxNzA3MDYzMFowSzEL
MAkGA1UEBhMCSlAxEDAOBgNVBAgMB0Z1a3Vva2ExEDAOBgNVBAoMB2V4YW1wbGUx
GDAWBgNVBAMMD2V4YW1wbGUgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAKyZnhB9Yy0BRi8Qq51R3Cm2176MGLgREqVHER1qRvhgEtstgAej
KDS6MZFFW6TiWqYzLpAntYV9QpFtfN3xezbYw46HtO0nKQnIY32xvqAUiIHmMx0t
i979f1JIgDbK/7TToU6r5E8yWtPRxsMVkNECoqJe7P1ahVry6J7R5Boj8Iuv7B7B
98syKZM3xgeD6tt7Q4pX6ToQ0cf6A+PpFJz5a5ZC/U+Z4/AEVwie3aHSlGYT4KVK
A2aaCkiKESnKr4FpBCJPDRYPMKTbs6s3V1P0zEkGUsY08/HgB2cYllGTPPzQMj0I
CY+RgG+CBTJk+4Z/Sd1kjpWRlb1RSDOvghUCAwEAAaNgMF4wHQYDVR0OBBYEFHJk
MSj2g8OPQWsms5k3SuJ7wW0kMB8GA1UdIwQYMBaAFHJkMSj2g8OPQWsms5k3SuJ7
wW0kMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA
A4IBAQBb9cbUScQKgBzyNFDGhlOEs3LsJfPb0K/ghwOysRjdyqLyS/DXrTUByYSy
MqsfHodR6eq6jrCasqE0jLuyDZ8IxJFpTKdIXLTlAS/HTOh6zOSUcNJlZA8rA4IL
3iQxg8d41++hCQnGnieFjIAuhR4D+5Lo6KOJokocMA5e9Dw6VNg7dBsFQH+NiZJ+
Os/ZvdRwJY95LbpoCbWxFMsrStabfrAMplFFlWx0VpYOQ7thMPkB3y4esauIfhWU
Y9tCkbrFlthF73nXQVP9iIyIMQ6P/Y8NU7cyFtXXepkk+boQrYPw5n8OWQng8b9V
I4ec/xj4+9L/nvMOfFwSAKxNfWWm
-----END CERTIFICATE-----
root@rootCA:/opt/pki/rootCA#

OK

証明書のいろいろを確認する

openssl x509 -text -in rootCA_crt.pem -noout
openssl x509 -purpose -in rootCA_crt.pem -noout

log

root@rootCA:/opt/pki/rootCA# openssl x509 -text -in rootCA_crt.pem -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = JP, ST = Fukuoka, O = example, CN = example Root CA
        Validity
            Not Before: Feb 19 07:06:30 2022 GMT
            Not After : Feb 17 07:06:30 2032 GMT
        Subject: C = JP, ST = Fukuoka, O = example, CN = example Root CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:ac:99:9e:10:7d:63:2d:01:46:2f:10:ab:9d:51:
                    dc:29:b6:d7:be:8c:18:b8:11:12:a5:47:11:1d:6a:
                    46:f8:60:12:db:2d:80:07:a3:28:34:ba:31:91:45:
                    5b:a4:e2:5a:a6:33:2e:90:27:b5:85:7d:42:91:6d:
                    7c:dd:f1:7b:36:d8:c3:8e:87:b4:ed:27:29:09:c8:
                    63:7d:b1:be:a0:14:88:81:e6:33:1d:2d:8b:de:fd:
                    7f:52:48:80:36:ca:ff:b4:d3:a1:4e:ab:e4:4f:32:
                    5a:d3:d1:c6:c3:15:90:d1:02:a2:a2:5e:ec:fd:5a:
                    85:5a:f2:e8:9e:d1:e4:1a:23:f0:8b:af:ec:1e:c1:
                    f7:cb:32:29:93:37:c6:07:83:ea:db:7b:43:8a:57:
                    e9:3a:10:d1:c7:fa:03:e3:e9:14:9c:f9:6b:96:42:
                    fd:4f:99:e3:f0:04:57:08:9e:dd:a1:d2:94:66:13:
                    e0:a5:4a:03:66:9a:0a:48:8a:11:29:ca:af:81:69:
                    04:22:4f:0d:16:0f:30:a4:db:b3:ab:37:57:53:f4:
                    cc:49:06:52:c6:34:f3:f1:e0:07:67:18:96:51:93:
                    3c:fc:d0:32:3d:08:09:8f:91:80:6f:82:05:32:64:
                    fb:86:7f:49:dd:64:8e:95:91:95:bd:51:48:33:af:
                    82:15
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24
            X509v3 Authority Key Identifier:
                keyid:72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24

            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
         5b:f5:c6:d4:49:c4:0a:80:1c:f2:34:50:c6:86:53:84:b3:72:
         ec:25:f3:db:d0:af:e0:87:03:b2:b1:18:dd:ca:a2:f2:4b:f0:
         d7:ad:35:01:c9:84:b2:32:ab:1f:1e:87:51:e9:ea:ba:8e:b0:
         9a:b2:a1:34:8c:bb:b2:0d:9f:08:c4:91:69:4c:a7:48:5c:b4:
         e5:01:2f:c7:4c:e8:7a:cc:e4:94:70:d2:65:64:0f:2b:03:82:
         0b:de:24:31:83:c7:78:d7:ef:a1:09:09:c6:9e:27:85:8c:80:
         2e:85:1e:03:fb:92:e8:e8:a3:89:a2:4a:1c:30:0e:5e:f4:3c:
         3a:54:d8:3b:74:1b:05:40:7f:8d:89:92:7e:3a:cf:d9:bd:d4:
         70:25:8f:79:2d:ba:68:09:b5:b1:14:cb:2b:4a:d6:9b:7e:b0:
         0c:a6:51:45:95:6c:74:56:96:0e:43:bb:61:30:f9:01:df:2e:
         1e:b1:ab:88:7e:15:94:63:db:42:91:ba:c5:96:d8:45:ef:79:
         d7:41:53:fd:88:8c:88:31:0e:8f:fd:8f:0d:53:b7:32:16:d5:
         d7:7a:99:24:f9:ba:10:ad:83:f0:e6:7f:0e:59:09:e0:f1:bf:
         55:23:87:9c:ff:18:f8:fb:d2:ff:9e:f3:0e:7c:5c:12:00:ac:
         4d:7d:65:a6
root@rootCA:/opt/pki/rootCA#
root@rootCA:/opt/pki/rootCA# openssl x509 -purpose -in rootCA_crt.pem -noout
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
root@rootCA:/opt/pki/rootCA#

中身も確認できた
目的を見てみると、 CA として作られたものだと分かる

コンテナから抜ける

exit

Intermediate CA を作る

コンテナに入る

lxc shell interCA

ディレクトリ作ったり準備

やることは root CA と同じ

mkdir -p /opt/pki/{interCA,tmp}/config

openssl_ca.cnf を作る

作るのだが、 root で作った openssl_ca.cnf と同じもので良いので、コピーを手に入れる
今回は lxc なので、 lxc ホスト経由でコピーする

exit
lxc file pull rootCA/opt/pki/rootCA/config/openssl_ca.cnf .
lxc file push ./openssl_ca.cnf interCA/opt/pki/interCA/config/
lxc exec interCA -- ls /opt/pki/interCA/config/

push できたか?

$ lxc exec interCA -- ls /opt/pki/interCA/config/
openssl_ca.cnf

OK

コンテナに入る

lxc shell interCA

Private intermediate ca を作る事前準備

cd /opt/pki/interCA/

mkdir {newcerts,requests}
echo "01" > serial
echo "00" > crlnumber
# echo "01" | sudo tee serial
# echo "00" | sudo tee crlnumber
touch index.txt

Private key を作る

openssl genrsa \
  -out interCA_key.pem \
  -aes256 \
  -passout pass:inter_ca_pass_phrase \
  2048

CSR を作る

組織名は example2 とする

openssl req -new \
  -subj "/C=JP/ST=Fukuoka/O=example2/CN=example2 Intermediate CA" \
  -out interCA_csr.pem \
  -key interCA_key.pem \
  -passin pass:inter_ca_pass_phrase

interCA の CSR を rootCA に送る

lxc ホスト経由で渡す
/opt/pki/rootCA/requests/ ディレクトリへ送る

# 今のコンテナを抜ける
exit
lxc file pull interCA/opt/pki/interCA/interCA_csr.pem .
lxc file push -v ./interCA_csr.pem rootCA/opt/pki/rootCA/requests/

確認

$ lxc file push -v ./interCA_csr.pem rootCA/opt/pki/rootCA/requests/
INFO[02-19|16:56:23] Pushing interCA_csr.pem to /opt/pki/rootCA/requests/interCA_csr.pem (file)

interCA の CSR に root CA が署名して 証明書を発行する

# コンテナに入る
lxc shell rootCA

cd /opt/pki/rootCA

openssl

openssl ca \
  -batch \
  -config config/openssl_ca.cnf \
  -extensions v3_ca \
  -policy policy_anything \
  -in  requests/interCA_csr.pem \
  -out requests/interCA_crt.pem \
  -cert rootCA_crt.pem \
  -keyfile rootCA_key.pem \
  -passin pass:root_ca_pass_phrase

log

root@rootCA:/opt/pki/rootCA# openssl ca \
>   -batch \
>   -config config/openssl_ca.cnf \
>   -extensions v3_ca \
>   -policy policy_anything \
>   -in  requests/interCA_csr.pem \
>   -out requests/interCA_crt.pem \
>   -cert rootCA_crt.pem \
>   -keyfile rootCA_key.pem \
>   -passin pass:root_ca_pass_phrase
Using configuration from config/openssl_ca.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Feb 19 08:14:32 2022 GMT
            Not After : Feb 17 08:14:32 2032 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Fukuoka
            organizationName          = example2
            commonName                = example2 Intermediate CA
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                9A:6D:AC:76:DF:44:02:E4:A4:79:B1:9D:34:B6:F2:B3:94:7C:96:98
            X509v3 Authority Key Identifier:
                keyid:72:64:31:28:F6:83:C3:8F:41:6B:26:B3:99:37:4A:E2:7B:C1:6D:24

            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
Certificate is to be certified until Feb 17 08:14:32 2032 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated
root@rootCA:/opt/pki/rootCA#

Signature ok とでた。 OK

中身の確認

openssl x509 -text -in requests/interCA_crt.pem -noout
openssl x509 -purpose -in requests/interCA_crt.pem -noout

interCA に CRT を 送る

lxc host から

# コンテナから出る
exit

lxc file pull -v rootCA/opt/pki/rootCA/requests/interCA_crt.pem .
lxc file push -v ./interCA_crt.pem interCA/opt/pki/interCA/

一部 log

$ lxc file pull -v rootCA/opt/pki/rootCA/requests/interCA_crt.pem .
INFO[02-19|17:16:32] Pulling interCA_crt.pem from opt/pki/rootCA/requests/interCA_crt.pem (file)

$ lxc file push -v ./interCA_crt.pem interCA/opt/pki/interCA/
INFO[02-19|17:17:04] Pushing interCA_crt.pem to /opt/pki/interCA/interCA_crt.pem (file)

OK

サーバのワイルドカード証明書を作る

準備1

作業ディレクトリの作成

# コンテナに入る
lxc shell serverCA

mkdir -p /opt/pki/server
cd $_

サーバ秘密鍵の作成

パスワード有りで作成する

openssl genrsa \
  -out server_key.pem \
  -aes256 \
  -passout pass:serverprivkeypass \
  2048

server_key.pem をバックアップして、パスフレーズなしの秘密鍵を作る
これをしないと、web サーバの再起動時に毎回パスフレーズを聞かれる
何かをトリガーにしてサーバが再起動したときに自動的にサービスが立ち上がらない可能性があるので、やっておく

cp -iv server_key.pem server_key.pem.with_pass_phrase

openssl rsa \
  -in  server_key.pem \
  -out server_key.pem \
  -passin pass:serverprivkeypass

名前を決める

ドメイン名を決める
とは言え、 gTLD 衝突問題等あるので、一時的に使う場合は今現在存在しないもので良い
長期的に使う場合は、なんでもいいので名前を取ろう

gTLD 衝突問題

www.nic.ad.jp

短期でも名前を使いたいなら internal とかを使うといいかも?

参考

pdwslmr.netlify.app

無料でドメイン取れるところ

www.freenom.com

こういうところで、ドメイン名を無料で取れる
個人的には、 google domains がいいだろうと思う

で、実は、IP アドレスでもOK

今回は IP アドレスでやる

10.164.40.175
がサーバの IP アドレスなので、これを登録する

SAN 付きの CSR ファイルを作る為の設定ファイルを作る

cd /opt/pki/server
mkdir config

SAN を記載したファイルを作る

cat << 'EOL' | sudo tee config/san.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 (eg, city)
0.organizationName              = Organization Name (eg, company)
commonName                      = Common Name (e.g. server FQDN or YOUR name)


[ req_ext ]
subjectAltName = @alt_names

[alt_names]
# Write SANs(Subject Alternative Names)
DNS.1 = 10.164.40.175
DNS.2 = localhost
IP.1 = 10.164.40.175
IP.2 = 127.0.0.1
EOL

CSR ファイルを作る

組織は something にしよう

openssl req -new \
  -subj "/C=JP/ST=Fukuoka/L=Example City/O=something/CN=10.164.40.175" \
  -config config/san.cnf \
  -out server_csr.pem \
  -key server_key.pem

確認

openssl req -text -in server_csr.pem -noout
# こっちでもいい
openssl req -text -in server_csr.pem

log

root@serverCA:/opt/pki/server# openssl req -text -in server_csr.pem -noout
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = JP, ST = Fukuoka, L = Example City, O = something, CN = 10.164.40.175
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:c7:9c:11:26:a3:28:62:d9:12:b1:30:34:36:03:
                    a6:80:db:51:1c:7c:f9:56:13:bb:be:4e:e6:d4:44:
                    65:a7:f7:c3:a1:28:94:8e:78:62:bb:7d:ee:0b:20:
                    9a:fa:f5:8c:b9:da:0c:30:e9:69:fe:9c:03:be:91:
                    93:10:4e:f5:54:85:dc:33:f4:40:3b:2e:03:1e:2a:
                    ab:e4:e0:b0:6f:b2:38:cf:c4:a2:2e:12:7b:d4:09:
                    a9:0d:c9:35:51:9b:96:49:65:f2:3c:6c:a8:b2:b5:
                    a2:65:f8:33:02:45:82:23:10:6c:be:fe:17:f3:7e:
                    cc:4c:d6:3b:69:29:26:df:20:9f:62:cd:d0:67:97:
                    20:63:60:dd:fe:a8:16:c8:49:93:15:93:34:d1:14:
                    c3:09:ab:df:0e:23:71:78:b1:2c:d2:e7:45:7b:7a:
                    8c:87:89:2b:54:f6:c3:b0:9a:5a:1b:02:f5:f9:df:
                    d6:a6:15:9b:d0:3d:6c:0c:72:a3:c2:b4:be:b7:62:
                    ef:4b:6b:6d:66:e4:75:9f:de:c2:5d:9d:6a:f0:a0:
                    18:48:ee:d2:21:9d:99:fd:6c:14:27:c2:9e:cb:07:
                    f6:f3:47:e9:df:58:fc:51:3b:a6:05:e1:ba:83:59:
                    76:38:9d:6d:d6:f6:ad:4b:dc:51:7a:c6:89:da:74:
                    e5:03
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name:
                DNS:10.164.40.175, DNS:localhost, IP Address:10.164.40.175, IP Address:127.0.0.1
    Signature Algorithm: sha256WithRSAEncryption
         17:b7:31:3d:35:a3:f2:38:e4:d5:4f:fb:c5:32:aa:7b:16:58:
         2e:96:c7:dd:ee:ba:4a:b9:b0:54:30:5b:48:af:83:c5:18:78:
         24:3f:2e:86:09:19:44:04:06:50:7e:23:04:df:9a:0a:7c:7b:
         b5:41:97:71:49:dc:fa:1f:28:01:2c:6b:8a:ce:e3:ac:66:e1:
         3d:ff:32:67:86:74:5f:b2:7c:52:29:15:98:c4:f8:fd:b1:4a:
         89:f0:16:c9:ec:11:00:f7:d2:eb:8f:f5:86:af:3d:f1:73:b2:
         07:e3:b0:a3:47:f8:3f:50:ee:b0:23:8b:b4:f4:71:7c:c4:38:
         ee:10:62:e3:dd:dc:e6:73:84:ec:1d:4f:bb:1e:d8:dc:97:4b:
         52:30:bf:65:25:aa:60:f2:ec:67:32:d2:60:4b:0e:36:1e:44:
         d3:45:cb:92:1c:b1:00:8e:b6:34:02:0f:6d:d7:33:f6:ad:b5:
         5f:00:c2:26:6e:80:93:a0:62:27:a9:37:48:2f:c7:e0:aa:86:
         f2:9d:e7:eb:57:50:b5:b9:e6:14:96:49:8f:df:a8:39:dd:3d:
         cb:21:1b:98:63:63:09:4f:21:28:45:2e:9a:fe:03:5d:4f:39:
         26:fb:86:5e:07:87:a3:69:12:0b:41:6c:1b:52:ee:b3:f7:7b:
         9f:2e:b5:e9
root@serverCA:/opt/pki/server#

CN10.164.40.175 がついていて
Subject Alternative Name に san.cnf で指定した DNS, IP が付与されているのが分かる

Intermediate CA に server_csr.pem を送付する

lxc host 経由

# serverCA から抜ける
exit

lxc file pull -v serverCA/opt/pki/server/server_csr.pem .
lxc file push -v ./server_csr.pem interCA/opt/pki/interCA/requests/

interCA の openssl の config ファイルを修正する

今のままだと SAN の値を折角 server csr で書き込んだのに、反映されない
反映されるように修正する

# interCA に入る
lxc shell interCA

cd /opt/pki/interCA/
cp -iv config/openssl_ca.cnf config/openssl_ca_copy_extensions.cnf
vim config/openssl_ca_copy_extensions.cnf

下記の行のコメントアウトを外す
# copy_extensions = copy

diff

root@interCA:/opt/pki/interCA# diff -uprN config/openssl_ca.cnf config/openssl_ca_copy_extensions.cnf
--- config/openssl_ca.cnf       2022-02-19 07:46:27.842366121 +0000
+++ config/openssl_ca_copy_extensions.cnf       2022-02-19 12:58:31.025098345 +0000
@@ -27,7 +27,7 @@ name_opt      = ca_default            # Subject Name o
 cert_opt       = ca_default            # Certificate field options

 # Extension copying option: use with caution.
-# copy_extensions = copy
+copy_extensions = copy

 # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
 # so this is commented out by default to leave a V1 CRL.
root@interCA:/opt/pki/interCA#

署名する

openssl ca \
  -config config/openssl_ca_copy_extensions.cnf \
  -policy policy_anything \
  -in requests/server_csr.pem \
  -out requests/server_crt.pem \
  -cert interCA_crt.pem \
  -keyfile interCA_key.pem \
  -passin pass:inter_ca_pass_phrase

log

root@interCA:/opt/pki/interCA# openssl ca \
>   -config config/openssl_ca_copy_extensions.cnf \
>   -policy policy_anything \
>   -in requests/server_csr.pem \
>   -out requests/server_crt.pem \
>   -cert interCA_crt.pem \
>   -keyfile interCA_key.pem \
>   -passin pass:inter_ca_pass_phrase
Using configuration from config/openssl_ca_copy_extensions.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Feb 19 13:26:20 2022 GMT
            Not After : Feb 17 13:26:20 2032 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Fukuoka
            localityName              = Example City
            organizationName          = something
            commonName                = 10.164.40.175
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                FA:96:B3:DE:53:EE:FF:7B:D2:30:8B:2E:BE:D0:43:78:3C:7F:C4:25
            X509v3 Authority Key Identifier:
                keyid:9A:6D:AC:76:DF:44:02:E4:A4:79:B1:9D:34:B6:F2:B3:94:7C:96:98

            X509v3 Subject Alternative Name:
                DNS:10.164.40.175, DNS:localhost, IP Address:10.164.40.175, IP Address:127.0.0.1
Certificate is to be certified until Feb 17 13:26:20 2032 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
root@interCA:/opt/pki/interCA#

ここだけ対話的になっている
確認の上、問題なければ、 y で進めよう

証明書の部分だけ抜き出す

下記のコマンドで全体が見える
証明書以外の情報も書き込まれている

cat requests/server_crt.pem

必要ない部分を消す

cp -iv requests/server_crt.pem requests/server_crt.pem.org
# この出力だけが欲しい
openssl x509 -in requests/server_crt.pem
# -out で同じファイル名にして保存する
openssl x509 -in requests/server_crt.pem -out requests/server_crt.pem
# 確認
cat requests/server_crt.pem

中身の確認

openssl x509 -text -in requests/server_crt.pem -noout
openssl x509 -purpose -in requests/server_crt.pem -noout

log

root@interCA:/opt/pki/interCA# openssl x509 -text -in requests/server_crt.pem -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = JP, ST = Fukuoka, O = example2, CN = example2 Intermediate CA
        Validity
            Not Before: Feb 19 13:26:20 2022 GMT
            Not After : Feb 17 13:26:20 2032 GMT
        Subject: C = JP, ST = Fukuoka, L = Example City, O = something, CN = 10.164.40.175
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:c7:9c:11:26:a3:28:62:d9:12:b1:30:34:36:03:
                    a6:80:db:51:1c:7c:f9:56:13:bb:be:4e:e6:d4:44:
                    65:a7:f7:c3:a1:28:94:8e:78:62:bb:7d:ee:0b:20:
                    9a:fa:f5:8c:b9:da:0c:30:e9:69:fe:9c:03:be:91:
                    93:10:4e:f5:54:85:dc:33:f4:40:3b:2e:03:1e:2a:
                    ab:e4:e0:b0:6f:b2:38:cf:c4:a2:2e:12:7b:d4:09:
                    a9:0d:c9:35:51:9b:96:49:65:f2:3c:6c:a8:b2:b5:
                    a2:65:f8:33:02:45:82:23:10:6c:be:fe:17:f3:7e:
                    cc:4c:d6:3b:69:29:26:df:20:9f:62:cd:d0:67:97:
                    20:63:60:dd:fe:a8:16:c8:49:93:15:93:34:d1:14:
                    c3:09:ab:df:0e:23:71:78:b1:2c:d2:e7:45:7b:7a:
                    8c:87:89:2b:54:f6:c3:b0:9a:5a:1b:02:f5:f9:df:
                    d6:a6:15:9b:d0:3d:6c:0c:72:a3:c2:b4:be:b7:62:
                    ef:4b:6b:6d:66:e4:75:9f:de:c2:5d:9d:6a:f0:a0:
                    18:48:ee:d2:21:9d:99:fd:6c:14:27:c2:9e:cb:07:
                    f6:f3:47:e9:df:58:fc:51:3b:a6:05:e1:ba:83:59:
                    76:38:9d:6d:d6:f6:ad:4b:dc:51:7a:c6:89:da:74:
                    e5:03
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                FA:96:B3:DE:53:EE:FF:7B:D2:30:8B:2E:BE:D0:43:78:3C:7F:C4:25
            X509v3 Authority Key Identifier:
                keyid:9A:6D:AC:76:DF:44:02:E4:A4:79:B1:9D:34:B6:F2:B3:94:7C:96:98

            X509v3 Subject Alternative Name:
                DNS:10.164.40.175, DNS:localhost, IP Address:10.164.40.175, IP Address:127.0.0.1
    Signature Algorithm: sha256WithRSAEncryption
         a1:fb:bf:2f:b2:9f:68:a7:0d:65:06:5f:d0:45:b0:eb:ce:d0:
         62:32:83:69:0e:cc:d2:3d:f8:98:52:ef:c0:38:8b:a8:a0:bd:
         a4:d8:7d:33:25:26:d0:5d:a4:80:0e:75:ab:c1:8e:14:61:ef:
         3d:2d:10:09:76:69:70:9e:48:8b:9a:99:e4:e5:1c:ba:08:ab:
         da:74:8a:f1:bc:30:cd:4b:6c:9c:21:5b:23:df:04:b7:40:24:
         db:10:3f:7b:4c:73:05:79:37:b7:4d:42:07:3f:95:e1:9f:79:
         a7:f9:3d:0b:7e:df:84:a1:70:a0:dc:90:8d:fa:2b:6b:da:f2:
         f6:fb:38:a2:63:82:00:5f:92:32:db:3c:6c:ca:44:48:5b:53:
         a4:46:79:aa:bc:df:7a:e8:3b:67:3f:a7:40:b5:3a:9e:c1:fe:
         b0:d2:88:a5:f3:51:88:71:3c:00:df:17:68:d0:72:36:da:20:
         3c:ab:fb:9c:46:5b:a1:64:26:b5:db:66:33:5c:b1:8b:72:55:
         7f:3f:0f:0c:50:1d:b5:81:13:d8:6f:a3:89:d5:13:f9:80:4b:
         72:f9:f8:11:2d:92:bf:e9:aa:72:a6:79:c7:59:cb:33:23:9f:
         4e:92:06:70:a9:f1:c3:4e:bf:ef:11:d7:cd:27:1f:ab:37:11:
         ea:8b:c5:f5
root@interCA:/opt/pki/interCA#
root@interCA:/opt/pki/interCA# openssl x509 -purpose -in requests/server_crt.pem -noout
Certificate purposes:
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
Netscape SSL server : Yes
Netscape SSL server CA : No
S/MIME signing : Yes
S/MIME signing CA : No
S/MIME encryption : Yes
S/MIME encryption CA : No
CRL signing : Yes
CRL signing CA : No
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : No
Time Stamp signing : No
Time Stamp signing CA : No
root@interCA:/opt/pki/interCA#

issuer に example2 Intermediate CA が見える
CN に 10.164.40.175 が見える
Subject Alternative Name に 10.164.40.175 ほか、設定した値が見える
purpose を見ると、 SSL server: YesSSL server CA: No になっている
OK

server に証明書を送る

サーバのワイルドカード証明書
intermediate CA の 証明書 を送る

手段は問わない
今回は lxc host 経由で行う
通常はメールなのかな?

# interCA を抜ける
exit

# サーバのワイルドカード証明書
lxc file pull -v interCA/opt/pki/interCA/requests/server_crt.pem .
lxc file push -v ./server_crt.pem serverCA/opt/pki/server/

# interCA の証明書
lxc file pull -v interCA/opt/pki/interCA/interCA_crt.pem .
lxc exec serverCA -- mkdir /opt/pki/interCA/
lxc file push -v ./interCA_crt.pem serverCA/opt/pki/interCA/

サーバに紐付ける証明書を作る

# serverCA に入る
lxc shell serverCA

cd /opt/pki/

nginx では以下の順
上は サーバ証明書
下は 中間CA証明書

ソフトウェアで違うことがあるので確認すること

参考

www.ssl.ph

公式のマニュアルを探せという話ですよね。ごめんなさい。

interCA_crt.pem で余計な文字があることがわかりました
とってあげます

openssl x509 -in interCA/interCA_crt.pem -out interCA/interCA_crt.pem

で、証明書を作る

cat server/server_crt.pem interCA/interCA_crt.pem | \
  sudo tee server/server.crt

こうなる

root@serverCA:/opt/pki# cat server/server_crt.pem interCA/interCA_crt.pem | \
>   sudo tee server/server.crt
-----BEGIN CERTIFICATE-----
MIID4DCCAsigAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJKUDEQ
MA4GA1UECAwHRnVrdW9rYTERMA8GA1UECgwIZXhhbXBsZTIxITAfBgNVBAMMGGV4
YW1wbGUyIEludGVybWVkaWF0ZSBDQTAeFw0yMjAyMTkxMzI2MjBaFw0zMjAyMTcx
MzI2MjBaMGIxCzAJBgNVBAYTAkpQMRAwDgYDVQQIDAdGdWt1b2thMRUwEwYDVQQH
DAxFeGFtcGxlIENpdHkxEjAQBgNVBAoMCXNvbWV0aGluZzEWMBQGA1UEAwwNMTAu
MTY0LjQwLjE3NTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMecESaj
KGLZErEwNDYDpoDbURx8+VYTu75O5tREZaf3w6EolI54Yrt97gsgmvr1jLnaDDDp
af6cA76RkxBO9VSF3DP0QDsuAx4qq+TgsG+yOM/Eoi4Se9QJqQ3JNVGblkll8jxs
qLK1omX4MwJFgiMQbL7+F/N+zEzWO2kpJt8gn2LN0GeXIGNg3f6oFshJkxWTNNEU
wwmr3w4jcXixLNLnRXt6jIeJK1T2w7CaWhsC9fnf1qYVm9A9bAxyo8K0vrdi70tr
bWbkdZ/ewl2davCgGEju0iGdmf1sFCfCnssH9vNH6d9Y/FE7pgXhuoNZdjidbdb2
rUvcUXrGidp05QMCAwEAAaOBrTCBqjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU+paz3lPu
/3vSMIsuvtBDeDx/xCUwHwYDVR0jBBgwFoAUmm2sdt9EAuSkebGdNLbys5R8lpgw
LwYDVR0RBCgwJoINMTAuMTY0LjQwLjE3NYIJbG9jYWxob3N0hwQKpCivhwR/AAAB
MA0GCSqGSIb3DQEBCwUAA4IBAQCh+78vsp9opw1lBl/QRbDrztBiMoNpDszSPfiY
Uu/AOIuooL2k2H0zJSbQXaSADnWrwY4UYe89LRAJdmlwnkiLmpnk5Ry6CKvadIrx
vDDNS2ycIVsj3wS3QCTbED97THMFeTe3TUIHP5Xhn3mn+T0Lft+EoXCg3JCN+itr
2vL2+ziiY4IAX5Iy2zxsykRIW1OkRnmqvN966DtnP6dAtTqewf6w0oil81GIcTwA
3xdo0HI22iA8q/ucRluhZCa122YzXLGLclV/Pw8MUB21gRPYb6OJ1RP5gEty+fgR
LZK/6apypnnHWcszI59OkgZwqfHDTr/vEdfNJx+rNxHqi8X1
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDezCCAmOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJKUDEQ
MA4GA1UECAwHRnVrdW9rYTEQMA4GA1UECgwHZXhhbXBsZTEYMBYGA1UEAwwPZXhh
bXBsZSBSb290IENBMB4XDTIyMDIxOTA4MTQzMloXDTMyMDIxNzA4MTQzMlowVTEL
MAkGA1UEBhMCSlAxEDAOBgNVBAgMB0Z1a3Vva2ExETAPBgNVBAoMCGV4YW1wbGUy
MSEwHwYDVQQDDBhleGFtcGxlMiBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC+ZmaonvR0MgdC4xem3aK+NTwQqGGLsFch1rRC
JqqxjO/DHAupft43Vzff/xmnWFGQjUoc0rTURFhuKp7FbknlmAkxoDZ3sDrBsgXA
0WaH7qkKmNEzHo3I485ptuCsxFsuVm4OgSVwo7IXnlSTZzO1SaTpM9Q2Oe+KFlEj
iLLfjjwlbpt7x/hIjumxZ9lLXVS8KbaInFauxQV4klDGarItFa7UrB6pcd5KM4KD
RjPSUXmWo1IhgQhHizKrWPTFkKoEC1n2B1Roqh/9PB57IaR1t2h6yENHIGNBpntc
8RpRHvaNeWN9oB6hsAKouyMCdiHRaWSkF33vPt21gHa7lRqTAgMBAAGjYDBeMB0G
A1UdDgQWBBSabax230QC5KR5sZ00tvKzlHyWmDAfBgNVHSMEGDAWgBRyZDEo9oPD
j0FrJrOZN0rie8FtJDAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq
hkiG9w0BAQsFAAOCAQEAQ7/yNUG0xXagIANfcm/uLTqkR2x+9j6iSC6OCEAnEK0C
P1GAD4cDyllLb0VTkZoO/2xgAGaKh87vmeWM8JFzW4CBP6J0FH2qWegi1fPTzSWU
XXOLgQ6mpEi/sR+utBkT9VHD04PUObtn6WhBVg+4kLUBiAWqn/mHQaMlnTbfqqYI
0++OSHSWox5XZYoemIKd1U2726Q8UkTEtPTDBptVbO5vVeARmfokBxw+4/bBi0bn
krcrJppYsb4/BYrGzPlJsT1hv8yY/xBRgJKyBmHlWu9DuVUyUisTCn8tvtV3xR06
nLKQm1uoJ6t8zi+TP/Jd79TP5wAtuEdKPMQ0Ra6SaA==
-----END CERTIFICATE-----
root@serverCA:/opt/pki#

nginx に紐づけてあげる

apt install -y nginx
cd /etc/nginx
vim sites-available/default
# SSL configuration のところをいじる
# こうなった
root@serverCA:/etc/nginx# grep -vE "^$|^\s*#" sites-available/default
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        listen 443 ssl default_server;
        ssl_certificate /opt/pki/server/server.crt;
        ssl_certificate_key /opt/pki/server/server_key.pem;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name _;
        location / {
                try_files $uri $uri/ =404;
        }
}
root@serverCA:/etc/nginx#

service restart

nginx -t
systemctl restart nginx

確認

root@serverCA:/etc/nginx# ss -altn
State              Recv-Q              Send-Q                           Local Address:Port                           Peer Address:Port             Process
LISTEN             0                   4096                             127.0.0.53%lo:53                                  0.0.0.0:*
LISTEN             0                   128                                    0.0.0.0:22                                  0.0.0.0:*
LISTEN             0                   511                                    0.0.0.0:443                                 0.0.0.0:*
LISTEN             0                   511                                    0.0.0.0:80                                  0.0.0.0:*
LISTEN             0                   128                                       [::]:22                                     [::]:*
LISTEN             0                   511                                       [::]:80                                     [::]:*
root@serverCA:/etc/nginx#

443 listen している rootCA から root 証明書を取ってくる

# serverCA から出る
exit
lxc file pull -v rootCA/opt/pki/rootCA/rootCA_crt.pem .
lxc file push -v ./rootCA_crt.pem serverCA/root/

# serverCA に入る
lxc shell serverCA

curl

root@serverCA:~# curl -sSv --cacert /root/rootCA_crt.pem https://10.164.40.175
*   Trying 10.164.40.175:443...
* TCP_NODELAY set
* Connected to 10.164.40.175 (10.164.40.175) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /root/rootCA_crt.pem
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=JP; ST=Fukuoka; L=Example City; O=something; CN=10.164.40.175
*  start date: Feb 19 13:26:20 2022 GMT
*  expire date: Feb 17 13:26:20 2032 GMT
*  subjectAltName: host "10.164.40.175" matched cert's IP address!
*  issuer: C=JP; ST=Fukuoka; O=example2; CN=example2 Intermediate CA
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: 10.164.40.175
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Sat, 19 Feb 2022 14:00:51 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Sat, 19 Feb 2022 13:47:14 GMT
< Connection: keep-alive
< ETag: "6210f4e2-264"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #0 to host 10.164.40.175 left intact
root@serverCA:~#

SAN が正しく設定されているので 10.164.40.175 でアクセスできている
TLS1.3 で暗号化されている
issuer に example2 Intermediate CA が見える
SSL certificate verify ok. と出力されている
コンテンツも 200 OK で返ってきている

OK

感想

長かった。
いろいろな記事を読んだけど、1 つのホストで全部の役割をこなしているため、実際には分かれているはずの機関が分かりづらかったり
openssl のサブコマンドの意味が通っていなかったり
署名するってなによ?
ってなったりした。

実際にやってみると署名することで issuer に情報が乗ったりしていることが分かったり
CSR を作る意味が分かったりしてとても良かったと思う

この記事が誰かの役に立つことを祈る(自分も含めてね)w

以上。