1. SSL/TLS証明書の基本構造
SSL/TLS証明書は、インターネット上の通信を暗号化し、接続先の正当性を証明するために不可欠な要素です。主に以下の要素で構成されます。
- 秘密鍵 (Private Key): サーバー側で厳重に保管される鍵。データの復号や署名に使用します。
- 公開鍵 (Public Key): 証明書に含まれ、データの暗号化や署名の検証に使用されます。
- 証明書署名要求 (CSR): 公開鍵と組織情報をまとめたファイルで、認証局(CA)に署名を依頼する際に提出します。
- 証明書 (Certificate): CAの署名が含まれた公開鍵情報。
2. 証明書管理システムのディレクトリ構成
スクリプトで効率的に管理するために、以下のようなディレクトリ構造を推奨します。
.
├── cert_manager.sh # メイン制御スクリプト
├── configs # 設定ファイル(openssl.cnfなど)
├── store # 生成された証明書の保存先
│ ├── ca # プライベートCA用
│ ├── internal # 自己署名証明書
│ └── issued # CAによって署名された証明書
└── logs # 実行ログ
3. OpenSSL設定ファイル(openssl.cnf)の最適化
SAN(Subject Alternative Names)などの拡張属性を正しく処理するため、カスタム設定ファイルを用意します。
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = v3_req
x509_extensions = v3_ca
prompt = no
[ req_distinguished_name ]
C = JP
ST = Tokyo
L = Chiyoda
O = Tech-Lab
CN = development.local
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ alt_names ]
DNS.1 = *.dev.local
DNS.2 = dev.local
4. Shellスクリプトによる自動生成の実装
以下は、自己署名証明書およびCA署名証明書を生成するためのベースとなるShellスクリプトの例です。
#!/bin/bash
# カラー出力定義
CLR_RESET="\033[0m"
CLR_SUCCESS="\033[32m"
CLR_WARN="\033[33m"
CLR_ERROR="\033[31m"
# ログ出力関数
report_status() {
echo -e "${CLR_SUCCESS}[SUCCESS]${CLR_RESET} $1"
}
report_error() {
echo -e "${CLR_ERROR}[ERROR]${CLR_RESET} $1"
exit 1
}
# 必要なディレクトリの準備
init_workspace() {
local base_dir="./store"
mkdir -p "${base_dir}"/{ca/private,internal,issued,logs}
chmod 700 "${base_dir}/ca/private"
}
# 自己署名証明書の生成
create_standalone_cert() {
local domain_name=$1
local output_path="./store/internal/${domain_name}"
mkdir -p "${output_path}"
# 秘密鍵の生成
openssl genrsa -out "${output_path}/server.key" 2048
# 自己署名証明書の生成(有効期限365日)
openssl req -x509 -new -nodes \
-key "${output_path}/server.key" \
-days 365 \
-out "${output_path}/server.crt" \
-subj "/C=JP/ST=Tokyo/O=InternalDev/CN=${domain_name}"
report_status "${domain_name} の自己署名証明書を作成しました。"
}
# プライベートCAの構築
setup_private_ca() {
local ca_root="./store/ca"
# CA秘密鍵
openssl genrsa -out "${ca_root}/private/ca.key" 4096
# 自署名によるCAルート証明書
openssl req -x509 -new -nodes \
-key "${ca_root}/private/ca.key" \
-sha256 -days 3650 \
-out "${ca_root}/ca.crt" \
-subj "/C=JP/ST=Tokyo/O=PrivateCA/CN=MyLocalCA"
report_status "プライベートCAを構築しました。"
}
# CAによる署名プロセスの実行
sign_with_ca() {
local target_fqdn=$1
local ca_root="./store/ca"
local target_dir="./store/issued/${target_fqdn}"
mkdir -p "${target_dir}"
# 1. サーバー秘密鍵の生成
openssl genrsa -out "${target_dir}/server.key" 2048
# 2. CSRの生成
openssl req -new \
-key "${target_dir}/server.key" \
-out "${target_dir}/server.csr" \
-subj "/C=JP/ST=Tokyo/O=AppService/CN=${target_fqdn}"
# 3. CAによる署名
openssl x509 -req \
-in "${target_dir}/server.csr" \
-CA "${ca_root}/ca.crt" \
-CAkey "${ca_root}/private/ca.key" \
-CAcreateserial \
-out "${target_dir}/server.crt" \
-days 825 -sha256
report_status "${target_fqdn} のCA署名済み証明書を発行しました。"
}
# メイン処理
case "$1" in
"init")
init_workspace
setup_private_ca
;;
"self")
create_standalone_cert "$2"
;;
"issue")
sign_with_ca "$2"
;;
*)
echo "Usage: $0 {init|self [domain]|issue [domain]}"
;;
esac
5. 証明書の検証とフォーマット変換
生成した証明書が正しいかどうかを確認し、必要に応じて異なるフォーマットへ変換します。
証明書情報の確認
# 内容の表示
openssl x509 -in ./store/issued/example.local/server.crt -text -noout
# 有効期限の確認
openssl x509 -in ./store/issued/example.local/server.crt -noout -enddate
フォーマットの変換
Windowsサーバーや特定のアプリケーションでは、PEM形式以外のフォーマットが必要になる場合があります。
- PEMからPKCS#12 (PFX)への変換:
openssl pkcs12 -export -out cert.pfx -inkey server.key -in server.crt -certfile ca.crt - PEMからDERへの変換:
openssl x509 -outform der -in server.crt -out server.der
6. 運用上のセキュリティ・ベストプラクティス
- CA秘密鍵の保護: 構築したCAの秘密鍵(ca.key)は、ネットワークから隔離された場所に保管するか、パスフレーズで保護してください。
- 最小限の有効期間: セキュリティ上の理由から、サーバー証明書の有効期間は必要以上に長く設定せず、定期的な更新を自動化することを推奨します。
- ファイルパーミッション: 秘密鍵ファイルの権限は、所有者のみが読み書きできる
600(rw-------) に設定してください。 - SANの活用: IPアドレスや複数のドメインで利用する場合は、Common Name (CN) だけでなく、Subject Alternative Names (SAN) を必ず定義してください。