OpenSSLとShellスクリプトを用いたSSL/TLS証明書発行の自動化ガイド

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. 運用上のセキュリティ・ベストプラクティス

  1. CA秘密鍵の保護: 構築したCAの秘密鍵(ca.key)は、ネットワークから隔離された場所に保管するか、パスフレーズで保護してください。
  2. 最小限の有効期間: セキュリティ上の理由から、サーバー証明書の有効期間は必要以上に長く設定せず、定期的な更新を自動化することを推奨します。
  3. ファイルパーミッション: 秘密鍵ファイルの権限は、所有者のみが読み書きできる 600 (rw-------) に設定してください。
  4. SANの活用: IPアドレスや複数のドメインで利用する場合は、Common Name (CN) だけでなく、Subject Alternative Names (SAN) を必ず定義してください。

タグ: OpenSSL Shell Script ssl/tls Security Certificate Management

10月31日 16:50 投稿