1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! # Armature ACME
//!
//! ACME (Automatic Certificate Management Environment) client for obtaining
//! and renewing SSL/TLS certificates from providers like Let's Encrypt.
//!
//! ## Features
//!
//! - ✅ **Automatic Certificate Management** - Obtain and renew certificates automatically
//! - ✅ **Multiple Providers** - Support for Let's Encrypt, ZeroSSL, BuyPass, and more
//! - ✅ **Challenge Types** - HTTP-01, DNS-01, and TLS-ALPN-01 challenges
//! - ✅ **Account Management** - Register and manage ACME accounts
//! - ✅ **External Account Binding** - Support for providers requiring EAB
//! - ✅ **Automatic Renewal** - Check and renew certificates before expiration
//!
//! ## Quick Start
//!
//! ```no_run
//! use armature_acme::{AcmeClient, AcmeConfig};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Configure ACME client for Let's Encrypt staging (testing)
//! let config = AcmeConfig::lets_encrypt_staging(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string(), "www.example.com".to_string()],
//! ).with_accept_tos(true);
//!
//! // Create client
//! let mut client = AcmeClient::new(config).await?;
//!
//! // Order certificate
//! let (cert_pem, key_pem) = client.order_certificate().await?;
//!
//! // Save certificate and key
//! client.save_certificate(&cert_pem, &key_pem).await?;
//!
//! Ok(())
//! }
//! ```
//!
//! ## Certificate Providers
//!
//! ### Let's Encrypt (Production)
//!
//! ```
//! use armature_acme::AcmeConfig;
//!
//! let config = AcmeConfig::lets_encrypt_production(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string()],
//! );
//! ```
//!
//! ### Let's Encrypt (Staging - for testing)
//!
//! ```
//! use armature_acme::AcmeConfig;
//!
//! let config = AcmeConfig::lets_encrypt_staging(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string()],
//! );
//! ```
//!
//! ### ZeroSSL (requires EAB)
//!
//! ```
//! use armature_acme::AcmeConfig;
//!
//! let config = AcmeConfig::zerossl(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string()],
//! "your_eab_kid".to_string(),
//! "your_eab_hmac_key".to_string(),
//! );
//! ```
//!
//! ## Challenge Types
//!
//! ### HTTP-01 Challenge
//!
//! HTTP-01 challenges require serving a file at a specific URL on port 80.
//!
//! ```
//! use armature_acme::{AcmeConfig, ChallengeType};
//!
//! let config = AcmeConfig::lets_encrypt_staging(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string()],
//! ).with_challenge_type(ChallengeType::Http01);
//! ```
//!
//! ### DNS-01 Challenge
//!
//! DNS-01 challenges require creating a TXT record in your DNS zone.
//! This is required for wildcard certificates.
//!
//! ```
//! use armature_acme::{AcmeConfig, ChallengeType};
//!
//! let config = AcmeConfig::lets_encrypt_staging(
//! vec!["admin@example.com".to_string()],
//! vec!["*.example.com".to_string()],
//! ).with_challenge_type(ChallengeType::Dns01);
//! ```
//!
//! ### TLS-ALPN-01 Challenge
//!
//! TLS-ALPN-01 challenges require TLS configuration on port 443.
//!
//! ```
//! use armature_acme::{AcmeConfig, ChallengeType};
//!
//! let config = AcmeConfig::lets_encrypt_staging(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string()],
//! ).with_challenge_type(ChallengeType::TlsAlpn01);
//! ```
//!
//! ## Integration with Armature
//!
//! Use ACME certificates with Armature's HTTPS server:
//!
//! ```no_run
//! use armature_acme::{AcmeClient, AcmeConfig};
//!
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! // Obtain certificate
//! let config = AcmeConfig::lets_encrypt_production(
//! vec!["admin@example.com".to_string()],
//! vec!["example.com".to_string()],
//! ).with_accept_tos(true);
//!
//! let mut client = AcmeClient::new(config).await?;
//! let (cert_pem, key_pem) = client.order_certificate().await?;
//! let (cert_path, key_path) = client.save_certificate(&cert_pem, &key_pem).await?;
//!
//! // Use with Armature
//! // let tls_config = TlsConfig::from_pem_files(&cert_path, &key_path)?;
//! // app.listen_https(443, tls_config).await?;
//! # Ok(())
//! # }
//! ```
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;