文档版本: 1.0
项目版本: v0.4.0
更新时间: 2026-02-07
编辑: houseme
┌─────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌─────────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ CLI Tools │ │ Web Server │ │ Libraries │ │
│ └────────┬────────┘ └──────┬───────┘ └──────┬─────┘ │
└───────────┼──────────────────┼──────────────────┼────────┘
│ │ │
┌───────────▼──────────────────▼──────────────────▼────────┐
│ 编排层 (Orchestration) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │Provisioner│ │Validator │ │Renewer │ │Cleanup │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │
│ ┌──────────────────────────────────────────────────────┐│
│ │ Task State Machine (Orchestrator) ││
│ └──────────────────────────────────────────────────────┘│
└───────────┬─────────────────────────────────────────┬────┘
│ │
┌───────────▼─────────────────────────────────────────▼────┐
│ 业务逻辑层 (Business Logic) │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌────────────────┐│
│ │ Account │ │ Order │ │Challenge │ │ Certificate ││
│ └─────────┘ └─────────┘ └──────────┘ └────────────────┘│
│ ┌──────────────────────────────────────────────────────┐│
│ │ Protocol (ACME v2 / RFC 8555) ││
│ │ Directory | Nonce | JWS | Authorization | Objects ││
│ └──────────────────────────────────────────────────────┘│
└───────────┬──────────────────────────────────────┬────────┘
│ │
┌───────────▼──────────────────────────────────────▼────────┐
│ 传输和支持层 (Transport & Support) │
│ ┌──────────────┐ ┌─────────────┐ ┌────────────────────┐ │
│ │HTTP Client │ │Retry Policy │ │Rate Limiter │ │
│ └──────────────┘ └─────────────┘ └────────────────────┘ │
│ ┌──────────────┐ ┌─────────────┐ ┌────────────────────┐ │
│ │Config Mgmt │ │Crypto (ECC) │ │Encoding (B64/PEM) │ │
│ └──────────────┘ └─────────────┘ └────────────────────┘ │
└───────────┬──────────────────────────────────────┬────────┘
│ │
┌───────────▼──────────────────────────────────────▼────────┐
│ 持久化和观测层 (Persistence & Observability) │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │File Storage │ │Redis Storage │ │Encrypted Storage │ │
│ └─────────────┘ └──────────────┘ └────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Metrics (Prometheus) | Logging (Tracing) | Events │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
负责用户交互和外部集成。
src/cli/)args.rs - 使用 clap 的参数定义commands/obtain.rs - 证书申请命令commands/renew.rs - 证书续期命令commands/daemon.rs - 后台守护进程commands/info.rs - 证书信息查看CommandHandler, OutputFormattersrc/server/) [计划中]GET /api/certificates - 列表POST /api/certificates - 新建GET /api/status - 健康检查src/lib.rs)AcmeClient, AcmeConfig, 各类型和 trait协调各业务模块,实现高层工作流。
CertificateProvisioner 负责驱动订单、挑战和最终签发的全流程。支持状态汇报和异步执行。
pub struct CertificateProvisioner {
pub task_id: String,
pub status: Arc<RwLock<OrchestrationStatus>>,
// ...
}
所有编排器实现 Orchestrator trait,提供统一的异步任务处理能力。
#[async_trait]
pub trait Orchestrator: Send + Sync {
async fn execute(&mut self) -> Result<()>;
fn status(&self) -> OrchestrationStatus;
}
AcmeX 采用 “Post-Task-Polling” 模式处理耗时的 ACME 流程:
POST /api/orders 返回 202 Accepted 及 task_id。Provisioner。GET /api/orders/:id 检查进度。GET /api/certificates/:id 下载证书。CLI 用户输入
↓
┌─────────────────────┐
│ AcmeClient (主入口) │
└──────────┬──────────┘
↓
┌──────────────────────────────────────┐
│ CertificateProvisioner (编排器) │
└──┬───────────────┬──────────────┬────┘
↓ ↓ ↓
AccountMgr OrderManager ChallengeSolver
↓ ↓ ↓
Protocol Protocol DNS/HTTP
JWS/Directory Nonce Validation
↓ ↓ ↓
HttpClient (传输层,重试+限流)
↓
ACME 服务器
Certificate
├── certificate: X509 PEM
├── private_key: PEM encoded
├── chain: Vec<Certificate>
├── not_before: DateTime
├── not_after: DateTime
├── domains: Vec<String>
└── serial_number: String
Order
├── id: String
├── status: OrderStatus
├── identifiers: Vec<Identifier>
├── authorizations: Vec<Authorization>
├── certificate_url: Option<String>
├── finalize_url: String
└── created_at: DateTime
Authorization
├── identifier: Identifier
├── status: AuthorizationStatus
├── challenges: Vec<Challenge>
├── expires: DateTime
└── wildcard: bool
Challenge
├── type: ChallengeType
├── url: String
├── status: ChallengeStatus
├── token: String
└── validated: Option<DateTime>
acmex
├── async-trait # 异步 trait 支持
├── axum # Web 框架
├── base64 # Base64 编码
├── clap # CLI 参数
├── jiff # 时间处理
├── hickory-resolver # DNS 解析
├── pem # PEM 编码/解码
├── rcgen # CSR/证书生成
├── reqwest # HTTP 客户端
├── serde # 序列化
├── sha2 # 哈希算法
├── tokio # 异步运行时
├── tracing # 日志和追踪
├── aws-lc-rs 或 ring # 加密后端
└── redis (可选) # Redis 支持
lib.rs (公开 API)
├── protocol/ (底层)
│ ├── directory.rs
│ ├── nonce.rs
│ ├── jws.rs
│ └── objects.rs
├── account/ (依赖 protocol)
├── order/ (依赖 account, protocol)
├── challenge/ (依赖 protocol, transport)
├── client/ (依赖 account, order, challenge)
├── storage/ (独立)
├── renewal/ (依赖 client, storage)
├── metrics/ (独立)
├── transport/ (底层)
├── crypto/ (底层)
└── cli/ (依赖所有)
通过 trait 实现可插拔架构:
pub trait DnsProvider: Send + Sync {
async fn create_txt_record(&self, domain: &str, value: &str) -> Result<String>;
async fn delete_txt_record(&self, domain: &str, record_id: &str) -> Result<()>;
async fn query_txt_record(&self, domain: &str) -> Result<Vec<String>>;
}
添加新提供商:
src/dns/providers/ 下创建文件DnsProvider traitpub trait StorageBackend: Send + Sync {
async fn save(&self, key: &str, value: &[u8]) -> Result<()>;
async fn load(&self, key: &str) -> Result<Option<Vec<u8>>>;
async fn delete(&self, key: &str) -> Result<()>;
}
支持的后端:
pub trait Middleware: Send + Sync {
async fn before_request(&self, url: &str, method: &str) -> Result<()>;
async fn after_response(&self, url: &str, response: &HttpResponse) -> Result<()>;
async fn on_error(&self, url: &str, error: &AcmeError) -> Result<()>;
}
pub trait ChallengeSolver: Send + Sync {
async fn prepare(&self, authorization: &Authorization) -> Result<()>;
async fn validate(&self, authorization: &Authorization) -> Result<bool>;
async fn cleanup(&self, authorization: &Authorization) -> Result<()>;
fn challenge_type(&self) -> ChallengeType;
}
[features]
default = ["aws-lc-rs"]
# 加密后端
aws-lc-rs = ["dep:aws-lc-rs"]
ring-crypto = ["dep:ring"]
# 存储后端
redis = ["dep:redis"]
# DNS 提供商
dns-cloudflare = []
dns-digitalocean = []
dns-linode = []
dns-route53 = []
dns-azure = [] # 计划
dns-gcloud = [] # 计划
# CA 服务
google-ca = []
zerossl-ca = []
# 功能模块
metrics = []
cli = []
pub struct HttpClientConfig {
pub pool_size: usize,
pub timeout: Duration,
pub follow_redirects: bool,
}
pub struct NonceManager {
pool: Vec<String>, // 预缓存 nonce
endpoint: String,
}
tokio::spawn 处理独立任务Arc<T> 共享所有权Mutex 而不是 RwLock 减少竞争zeroize 清除敏感数据文档版本: 1.0
最后更新: 2026-02-07
维护者: houseme