f66a36d0f4
Signed-off-by: Catty Steve <4795515+Catty2014@user.noreply.gitee.com>
145 lines
4.5 KiB
Rust
145 lines
4.5 KiB
Rust
use clap::{Parser, Subcommand};
|
|
use std::path::PathBuf;
|
|
use workshop_cert::{CertConfig, CertificateGenerator, Result};
|
|
|
|
#[derive(Parser)]
|
|
#[command(name = "workshop-certgen")]
|
|
#[command(about = "Generate TLS certificates for Workshop CI/CD system")]
|
|
struct Cli {
|
|
#[command(subcommand)]
|
|
command: Commands,
|
|
|
|
/// Configuration file path
|
|
#[arg(short, long, default_value = "cert.toml")]
|
|
config: PathBuf,
|
|
|
|
/// Output directory for certificates
|
|
#[arg(short, long, default_value = "./certs")]
|
|
output_dir: PathBuf,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
enum Commands {
|
|
/// Generate CA certificate (one-time operation)
|
|
GenCa,
|
|
|
|
/// Generate server certificate (one-time operation)
|
|
GenServer,
|
|
|
|
/// Generate client certificate(s)
|
|
GenClient {
|
|
/// Client ID(s) to generate certificates for
|
|
#[arg(required = true)]
|
|
client_ids: Vec<String>,
|
|
},
|
|
|
|
/// Generate all certificates (CA, server, and sample client)
|
|
GenAll {
|
|
/// Also generate sample client certificates
|
|
#[arg(short, long)]
|
|
with_clients: bool,
|
|
|
|
/// Number of sample client certificates to generate
|
|
#[arg(short, long, default_value = "3")]
|
|
sample_count: usize,
|
|
},
|
|
|
|
/// Show current configuration
|
|
ShowConfig,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
env_logger::init();
|
|
let args = Cli::parse();
|
|
|
|
// 加载配置
|
|
let config = if args.config.exists() {
|
|
CertConfig::from_file(&args.config)?
|
|
} else {
|
|
println!("⚠️ 配置文件 {} 不存在,使用默认配置", args.config.display());
|
|
CertConfig::default_config()
|
|
};
|
|
|
|
let generator = CertificateGenerator::new(config, args.output_dir.clone());
|
|
generator.ensure_output_dir()?;
|
|
|
|
match args.command {
|
|
Commands::GenCa => {
|
|
println!("🔐 生成 CA 证书...");
|
|
generator.generate_ca()?;
|
|
}
|
|
|
|
Commands::GenServer => {
|
|
println!("🔐 生成服务器证书...");
|
|
|
|
// 首先需要 CA 证书
|
|
let ca_bundle = if generator.output_dir.join("ca-cert.pem").exists() {
|
|
// 从文件加载现有的 CA 证书
|
|
let cert_pem = std::fs::read_to_string(generator.output_dir.join("ca-cert.pem"))?;
|
|
let key_pem = std::fs::read_to_string(generator.output_dir.join("ca-key.pem"))?;
|
|
|
|
workshop_cert::CertificateBundle {
|
|
certificate: cert_pem,
|
|
private_key: key_pem,
|
|
public_key: None,
|
|
}
|
|
} else {
|
|
println!("❌ 未找到 CA 证书,请先运行 'gen-ca' 命令");
|
|
return Ok(());
|
|
};
|
|
|
|
generator.generate_server_certificate(&ca_bundle)?;
|
|
}
|
|
|
|
Commands::GenClient { client_ids } => {
|
|
println!("🔐 生成客户端证书: {:?}...", client_ids);
|
|
|
|
// 需要 CA 证书
|
|
let ca_bundle = if generator.output_dir.join("ca-cert.pem").exists() {
|
|
let cert_pem = std::fs::read_to_string(generator.output_dir.join("ca-cert.pem"))?;
|
|
let key_pem = std::fs::read_to_string(generator.output_dir.join("ca-key.pem"))?;
|
|
|
|
workshop_cert::CertificateBundle {
|
|
certificate: cert_pem,
|
|
private_key: key_pem,
|
|
public_key: None,
|
|
}
|
|
} else {
|
|
println!("❌ 未找到 CA 证书,请先运行 'gen-ca' 命令");
|
|
return Ok(());
|
|
};
|
|
|
|
generator.generate_client_certificates(&ca_bundle, &client_ids)?;
|
|
}
|
|
|
|
Commands::GenAll { with_clients, sample_count } => {
|
|
println!("🔐 生成所有证书...");
|
|
|
|
// 1. 生成 CA
|
|
let ca_bundle = generator.generate_ca()?;
|
|
|
|
// 2. 生成服务器证书
|
|
generator.generate_server_certificate(&ca_bundle)?;
|
|
|
|
// 3. 可选:生成示例客户端证书
|
|
if with_clients {
|
|
let sample_clients: Vec<String> = (1..=sample_count)
|
|
.map(|i| format!("sample{}", i))
|
|
.collect();
|
|
|
|
println!("👥 生成示例客户端证书: {:?}", sample_clients);
|
|
generator.generate_client_certificates(&ca_bundle, &sample_clients)?;
|
|
}
|
|
}
|
|
|
|
Commands::ShowConfig => {
|
|
println!("📋 当前配置:");
|
|
println!("{:#?}", generator.config);
|
|
}
|
|
}
|
|
|
|
println!("✅ 操作完成!");
|
|
Ok(())
|
|
}
|