Kamixitong/scripts/generate_ssl.py
2025-12-12 11:35:14 +08:00

187 lines
5.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
SSL证书生成脚本
用于生成自签名证书开发和测试或为Let's Encrypt准备
"""
import os
import sys
import subprocess
from pathlib import Path
def check_openssl():
"""检查OpenSSL是否已安装"""
try:
result = subprocess.run(['openssl', 'version'], capture_output=True, text=True)
print(f"✅ OpenSSL 已安装: {result.stdout.strip()}")
return True
except FileNotFoundError:
print("❌ OpenSSL 未安装")
print("\n请安装 OpenSSL:")
print(" Ubuntu/Debian: sudo apt-get install openssl")
print(" CentOS/RHEL: sudo yum install openssl")
print(" macOS: brew install openssl")
return False
def generate_self_signed_cert(domain="localhost", days=365):
"""生成自签名SSL证书"""
print(f"\n🔒 生成自签名SSL证书...")
print(f" 域名: {domain}")
print(f" 有效期: {days}")
# 创建证书目录
cert_dir = Path('certs')
cert_dir.mkdir(exist_ok=True)
# 证书文件路径
key_file = cert_dir / f"{domain}.key"
cert_file = cert_dir / f"{domain}.crt"
csr_file = cert_dir / f"{domain}.csr"
# 生成私钥
print("\n1. 生成私钥...")
cmd_key = [
'openssl', 'genrsa',
'-out', str(key_file),
'2048'
]
try:
subprocess.run(cmd_key, check=True, capture_output=True)
print(f" ✅ 私钥已生成: {key_file}")
except subprocess.CalledProcessError as e:
print(f" ❌ 生成私钥失败: {e.stderr.decode()}")
return False
# 生成证书签名请求
print("\n2. 生成证书签名请求...")
cmd_csr = [
'openssl', 'req',
'-new',
'-key', str(key_file),
'-out', str(csr_file),
'-subj', f'/C=CN/ST=Beijing/L=Beijing/O=KaMiXiTong/CN={domain}'
]
try:
subprocess.run(cmd_csr, check=True, capture_output=True)
print(f" ✅ 证书签名请求已生成: {csr_file}")
except subprocess.CalledProcessError as e:
print(f" ❌ 生成证书签名请求失败: {e.stderr.decode()}")
return False
# 生成自签名证书
print("\n3. 生成自签名证书...")
cmd_cert = [
'openssl', 'x509',
'-req',
'-in', str(csr_file),
'-signkey', str(key_file),
'-out', str(cert_file),
'-days', str(days)
]
try:
subprocess.run(cmd_cert, check=True, capture_output=True)
print(f" ✅ 自签名证书已生成: {cert_file}")
except subprocess.CalledProcessError as e:
print(f" ❌ 生成自签名证书失败: {e.stderr.decode()}")
return False
# 清理临时文件
csr_file.unlink()
# 设置文件权限
key_file.chmod(0o600)
cert_file.chmod(0o644)
print("\n✅ SSL证书生成完成!")
print(f"\n📁 文件位置:")
print(f" 私钥: {key_file.absolute()}")
print(f" 证书: {cert_file.absolute()}")
print(f"\n⚠️ 安全提醒:")
print(f" - 私钥文件权限已设置为600仅所有者可读写")
print(f" - 自签名证书仅用于开发和测试")
print(f" - 生产环境请使用 Let's Encrypt 或其他CA签发的证书")
return True
def generate_certbot_config(domain, email):
"""生成 Certbot 配置"""
print(f"\n🔒 生成 Certbot 配置...")
cert_dir = Path('certs')
cert_dir.mkdir(exist_ok=True)
config_content = f"""# Certbot 配置文件
# 申请 Let's Encrypt 证书
certbot certonly \\
--webroot \\
-w /var/www/html \\
-d {domain} \\
--email {email} \\
--agree-tos \\
--non-interactive \\
--keep-until-expiring
# 证书自动续期(添加到 crontab
0 12 * * * /usr/bin/certbot renew --quiet
"""
config_file = cert_dir / 'certbot.conf'
with open(config_file, 'w') as f:
f.write(config_content)
print(f"✅ Certbot 配置已生成: {config_file}")
print(f"\n📋 使用说明:")
print(f" 1. 安装 Certbot: sudo apt-get install certbot python3-certbot-nginx")
print(f" 2. 运行配置: sudo bash certbot.conf")
print(f" 3. 证书自动续期: 每天12点检查")
print(f" 4. 手动续期: sudo certbot renew")
def main():
"""主函数"""
print("=" * 60)
print("🔒 SSL证书生成工具")
print("=" * 60)
# 检查OpenSSL
if not check_openssl():
sys.exit(1)
# 获取用户输入
print("\n请选择证书类型:")
print("1. 自签名证书(开发和测试)")
print("2. Let's Encrypt 配置(生产环境推荐)")
choice = input("\n请选择 (1/2): ").strip()
if choice == '1':
domain = input("\n请输入域名或IP地址 (默认: localhost): ").strip() or 'localhost'
days = input("请输入有效期天数 (默认: 365): ").strip()
days = int(days) if days.isdigit() else 365
generate_self_signed_cert(domain, days)
elif choice == '2':
domain = input("\n请输入域名: ").strip()
email = input("请输入邮箱地址: ").strip()
if not domain or not email:
print("❌ 域名和邮箱不能为空")
sys.exit(1)
generate_certbot_config(domain, email)
else:
print("❌ 无效选择")
sys.exit(1)
print("\n" + "=" * 60)
print("✅ 完成!")
print("=" * 60)
if __name__ == '__main__':
main()