### Rust ACME Certificate Issuance and Error Handling Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Demonstrates the process of obtaining a TLS certificate using the ACME protocol with the acme-tls-alpn-01 library in Rust. It covers fetching the directory, creating a new account, requesting certificates, and handling potential errors at each step. This example requires the `acme-tls_alpn_01` and `reqwest` crates. ```rust use acme_tls_alpn_01::Acme; use acme_tls_alpn_01::letsencrypt::LetsEncrypt; let mut acme = Acme::::from_domain_names( vec!["example.com".to_string()].into_iter() ); match acme.directory(LetsEncrypt::ProductionEnvironment.directory_url()).await { Ok(directory) => { match acme.new_account("admin@example.com", &directory).await { Ok(account) => { match acme.request_certificates(&account, &directory).await { Ok(certificate) => { println!("Success: {}", certificate); } Err(e) => { eprintln!("Certificate request failed: {:?}", e); } } } Err(e) => { eprintln!("Account creation failed: {:?}", e); } } } Err(e) => { eprintln!("Directory fetch failed: {:?}", e); } } ``` -------------------------------- ### Get ACME Directory - Rust Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Retrieves the ACME server directory, which contains essential endpoint URLs for interacting with the ACME server. It supports Let's Encrypt's production and staging environments, as well as custom ACME server URLs. This operation is asynchronous. ```rust use acme_tls_alpn_01::letsencrypt::LetsEncrypt; // For production certificates let directory = acme .directory(LetsEncrypt::ProductionEnvironment.directory_url()) .await .unwrap(); // For testing (staging environment) let directory = acme .directory(LetsEncrypt::StagingEnvironment.directory_url()) .await .unwrap(); // Custom ACME server let directory = acme .directory("https://acme.example.com/directory") .await .unwrap(); ``` -------------------------------- ### Request Certificates with TLS-ALPN-01 Challenge - Rust Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Requests the issuance of TLS certificates for configured domains, automatically handling the TLS-ALPN-01 challenge. It requires an initialized ACME client, an authenticated account, and the ACME directory. The resulting PEM-encoded certificate (including private key) is saved to a file. ```rust use acme_tls_alpn_01::Acme; use acme_tls_alpn_01::letsencrypt::LetsEncrypt; let mut acme = Acme::::from_domain_names( vec!["example.com".to_string()].into_iter() ); let directory = acme .directory(LetsEncrypt::StagingEnvironment.directory_url()) .await .unwrap(); let account = acme .new_account("admin@example.com", &directory) .await .unwrap(); // Request certificates (this will handle the TLS-ALPN-01 challenge automatically) let certificate_pem = acme .request_certificates(&account, &directory) .await .unwrap(); // The certificate_pem contains both the private key and certificate chain std::fs::write("certificate.pem", certificate_pem).unwrap(); ``` -------------------------------- ### Initialize ACME Client with Domain Names - Rust Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Initializes an ACME client instance for managing TLS certificates for specified domain names. It requires domain names as input and provides a certificate resolver for TLS server integration. The client is generic over the HTTP client and response types. ```rust use acme_tls_alpn_01::Acme; // Create ACME client with domain names let mut acme = Acme::::from_domain_names( vec!["example.com".to_string(), "www.example.com".to_string()].into_iter() ); // Get the certificate resolver for integration with TLS server let resolver = acme.resolver.clone(); ``` -------------------------------- ### Create or Restore ACME Account - Rust Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Manages ACME accounts, allowing for the creation of new accounts with contact information or the restoration of existing accounts from saved credentials. It requires an ACME client, directory information, and optionally email and saved credentials. New accounts are persisted to a JSON file. ```rust use acme_tls_alpn_01::Acme; use acme_tls_alpn_01::letsencrypt::LetsEncrypt; let mut acme = Acme::::from_domain_names( vec!["example.com".to_string()].into_iter() ); let directory = acme .directory(LetsEncrypt::StagingEnvironment.directory_url()) .await .unwrap(); // Create new account let account = acme .new_account("admin@example.com", &directory) .await .unwrap(); // Save account credentials for reuse let account_json = account.to_json(); std::fs::write("account.json", account_json).unwrap(); // Restore account from saved credentials let saved_json = std::fs::read_to_string("account.json").unwrap(); let account = acme_tls_alpn_01::account::AccountMaterial::from_json( &saved_json, "admin@example.com", &directory, &acme.client ) .await .unwrap(); ``` -------------------------------- ### Rust: TLS Server with ACME Certificate Validation (Tokio + Rustls) Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Sets up a TLS server using Tokio and Rustls, integrating with ACME for automatic certificate validation via the TLS-ALPN-01 challenge. It handles both ACME challenge requests and regular HTTPS traffic, automatically serving valid certificates. ```rust use acme_tls_alpn_01::letsencrypt::LetsEncrypt; use acme_tls_alpn_01::Acme; use std::net::Ipv6Addr; use std::sync::Arc; use tokio::io::{copy, sink, split, AsyncWriteExt}; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls::rustls::server::Acceptor; use tokio_rustls::rustls::version::TLS13; use tokio_rustls::rustls::ServerConfig; use tokio_rustls::server::TlsStream; use tokio_rustls::LazyConfigAcceptor; #[tokio::main] async fn main() -> std::io::Result<()> { let domain_name = "example.com".to_string(); // Setup HTTPS listener on port 443 let https_listener = TcpListener::bind((Ipv6Addr::UNSPECIFIED, 443)).await?; // Create ACME client let mut acme = Acme::::from_domain_names( vec![domain_name].into_iter() ); let resolver = acme.resolver.clone(); // Configure TLS with ACME resolver let mut tls_config = ServerConfig::builder_with_protocol_versions(&[&TLS13]) .with_no_client_auth() .with_cert_resolver(resolver.clone()); // IMPORTANT: Include acme-tls/1 ALPN protocol for challenge validation tls_config.alpn_protocols = vec![b"http/1.1".to_vec(), b"acme-tls/1".to_vec()]; let tls_config = Arc::new(tls_config); // Spawn server task let server = tokio::spawn(async move { loop { if let Ok((tcp, _remote_addr)) = https_listener.accept().await { let mut acceptor = LazyConfigAcceptor::new(Acceptor::default(), tcp); let config = tls_config.clone(); if let Ok(start_handshake) = (&mut acceptor).await { let mut is_challenge = false; if let Ok(stream) = start_handshake .into_stream_with(config, |conn| { is_challenge = conn.alpn_protocol() == Some(b"acme-tls/1") }) .await { if is_challenge { // Handle ACME challenge request handle_acme_challenge(stream).await; } else { // Handle normal HTTPS request handle_https_request(stream).await; } } } } } }); // Request certificate let directory = acme .directory(LetsEncrypt::StagingEnvironment.directory_url()) .await .unwrap(); let account = acme .new_account("admin@example.com", &directory) .await .unwrap(); let certificate = acme .request_certificates(&account, &directory) .await .unwrap(); println!("Certificate obtained:\n{}", certificate); server.await.unwrap(); Ok(()) } async fn handle_acme_challenge(stream: TlsStream) { let (mut reader, mut writer) = split(stream); let _ = copy(&mut reader, &mut sink()).await; let _ = writer.write(b"HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n").await; } async fn handle_https_request(stream: TlsStream) { let (mut reader, mut writer) = split(stream); let _ = copy(&mut reader, &mut sink()).await; let _ = writer.write(b"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 2\r\n\r\nOK").await; } ``` -------------------------------- ### Rust: Roll Over ACME Account Keys Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Shows how to generate a new cryptographic key pair for an ACME account while preserving its identity. The new account credentials can then be saved to a file for future use. ```rust // Generate new account key pair while preserving account identity let new_account = account .update_key(&directory, &acme.client) .await .unwrap(); // Save the new account credentials let new_account_json = new_account.to_json(); std::fs::write("account.json", new_account_json).unwrap(); ``` -------------------------------- ### Rust: Integrate Certificate Resolver with TLS Configuration Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Illustrates how to integrate the ACME certificate resolver with a custom Rustls server configuration. The resolver automatically serves the correct certificates for both ACME challenges and regular HTTPS traffic, and handles certificate renewals. ```rust use rustls::server::ResolvesServerCert; use rustls::sign::CertifiedKey; use std::sync::Arc; // Access the resolver from the ACME client let resolver: Arc = acme.resolver.clone(); // Use with rustls ServerConfig let tls_config = tokio_rustls::rustls::ServerConfig::builder() .with_no_client_auth() .with_cert_resolver(resolver); // The resolver automatically handles: // - Serving challenge certificates during TLS-ALPN-01 validation // - Serving regular certificates for normal HTTPS traffic // - Updating certificates when renewed ``` -------------------------------- ### Rust: Update ACME Account Contact Information Source: https://context7.com/programingjd/acme-tls-alpn-01/llms.txt Demonstrates how to update the contact email address associated with an existing ACME account. This operation requires the current account, the ACME directory details, and the ACME client. ```rust // Update account contact email account .update_contact("newemail@example.com", &directory, &acme.client) .await .unwrap(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.