Files
2026-07-18 20:09:26 +08:00

57 lines
1.9 KiB
Python

"""
首次启动引导:为 CertCenter 自身生成自签证书
当 BASE_URL 使用 HTTPS 但证书不存在时自动执行
"""
import subprocess
from pathlib import Path
from urllib.parse import urlparse
from datetime import datetime, timedelta
def ensure_self_signed_cert(base_url: str, cert_dir: str):
"""
如果 CertCenter 自身的域名没有证书,生成一份自签证书
证书存放在 cert_dir/{domain}/ 目录下
"""
parsed = urlparse(base_url)
if parsed.scheme != "https":
return # HTTP 模式不需要证书
hostname = parsed.hostname
if not hostname:
return
cert_path = Path(cert_dir) / hostname / "fullchain.pem"
key_path = Path(cert_dir) / hostname / "private.key"
if cert_path.exists() and key_path.exists():
return # 证书已存在
# 创建目录
cert_path.parent.mkdir(parents=True, exist_ok=True)
print(f"[bootstrap] 为 {hostname} 生成自签证书...")
# 使用 openssl 生成自签证书
try:
subprocess.run(
[
"openssl", "req", "-x509", "-newkey", "rsa:2048",
"-keyout", str(key_path),
"-out", str(cert_path),
"-days", "365",
"-nodes",
"-subj", f"/CN={hostname}",
"-addext", f"subjectAltName=DNS:{hostname}",
],
capture_output=True,
check=True,
)
print(f"[bootstrap] 自签证书已生成: {cert_path}")
print(f"[bootstrap] 客户端部署脚本将使用 curl -k 跳过 TLS 验证")
except FileNotFoundError:
print("[bootstrap] 未找到 openssl,跳过自签证书生成")
print("[bootstrap] 请手动配置 HTTPS 证书,或使用 HTTP 模式")
except subprocess.CalledProcessError as e:
print(f"[bootstrap] 生成自签证书失败: {e.stderr.decode()}")