首次提交
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
首次启动引导:为 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()}")
|
||||
Reference in New Issue
Block a user