use crate::common::chaltestsrv::TestServ; use crate::common::pebble::PebbleBuilder; use crate::common::test_env::TestEnv; use acme2_eab::*; use common::pebble::Pebble; use data_encoding::BASE64URL_NOPAD; use openssl::pkey::PKey; use serde_json::json; use std::sync::Arc; use std::time::Duration; mod common; async fn pebble_http_client() -> reqwest::Client { let raw = tokio::fs::read("./certs/pebble.minica.pem").await.unwrap(); let cert = reqwest::Certificate::from_pem(&raw).unwrap(); reqwest::Client::builder() .add_root_certificate(cert) .build() .unwrap() } async fn pebble_directory(pebble: &Pebble) -> Arc { let http_client = pebble_http_client().await; DirectoryBuilder::new(pebble.directory_url.to_string()) .http_client(http_client) .build() .await .unwrap() } async fn pebble_account(pebble: &Pebble) -> Arc { let dir = pebble_directory(pebble).await; let mut builder = AccountBuilder::new(dir); let account = builder .contact(vec!["mailto:hello@lcas.dev".to_string()]) .terms_of_service_agreed(true) .build() .await .unwrap(); assert!(!account.id.is_empty()); account } #[tokio::test] async fn test_client_creation_pebble() { let mut env = TestEnv::new("test_client_creation_pebble"); let pebble = Pebble::new_default(&mut env).await.unwrap(); let dir = pebble_directory(&pebble).await; let meta = dir.meta.clone().unwrap(); assert_eq!(meta.caa_identities, None); assert_eq!(meta.website, None); env.stop().await; } #[tokio::test] async fn test_account_creation_pebble() { let mut env = TestEnv::new("test_account_creation_pebble"); let pebble = Pebble::new_default(&mut env).await.unwrap(); let dir = pebble_directory(&pebble).await; let mut builder = AccountBuilder::new(dir.clone()); let account = builder .contact(vec!["mailto:hello@lcas.dev".to_string()]) .terms_of_service_agreed(true) .build() .await .unwrap(); assert!(!account.id.is_empty()); let mut builder = AccountBuilder::new(dir.clone()); let account2 = builder .contact(vec!["mailto:hello@lcas.dev".to_string()]) .terms_of_service_agreed(true) .build() .await .unwrap(); assert!(!account.id.is_empty()); assert_eq!(account.status, AccountStatus::Valid); assert_eq!(account2.status, AccountStatus::Valid); env.stop().await; } #[tokio::test] async fn test_account_creation_pebble_eab() { let private_key = "zWNDZM6eQGHWpSRTPal5eIUYFTu7EajVIoguysqZ9wG44nMEtx3MUAsUDkMTQ12W"; let key_id = "kid-1"; let mut env = TestEnv::new("test_account_creation_pebble_eab"); let pebble = PebbleBuilder::new() .with_eab_keypair(key_id, private_key) .build(&mut env) .await .unwrap(); let dir = pebble_directory(&pebble).await; let eab_key = { let value_b64 = private_key; let value = BASE64URL_NOPAD.decode(value_b64.as_bytes()).unwrap(); PKey::hmac(&value).unwrap() }; let mut builder = AccountBuilder::new(dir.clone()); let account = builder .contact(vec!["mailto:hello@lcas.dev".to_string()]) .external_account_binding(key_id.to_string(), eab_key) .terms_of_service_agreed(true) .build() .await .unwrap(); assert!(!account.id.is_empty()); assert_eq!(account.status, AccountStatus::Valid); env.stop().await; } #[tokio::test] async fn test_order_http01_challenge_pebble_rsa() { let mut env = TestEnv::new("test_order_http01_challenge_pebble_rsa"); let testserv = TestServ::new(&mut env).await.unwrap(); let pebble = PebbleBuilder::new() .with_http_port(testserv.http_port) .build(&mut env) .await .unwrap(); let account = pebble_account(&pebble).await; let mut builder = OrderBuilder::new(account); let order = builder .add_dns_identifier("host.docker.internal".to_string()) .build() .await .unwrap(); let authorizations = order.authorizations().await.unwrap(); let client = reqwest::Client::new(); for auth in authorizations { let challenge = auth.get_challenge("http-01").unwrap(); assert_eq!(challenge.status, ChallengeStatus::Pending); let response = client .post(format!("{}add-http01", testserv.management_url)) .json(&json!({ "token": challenge.token, "content": challenge.key_authorization().unwrap().unwrap() })) .send() .await .unwrap(); assert!(response.status().is_success()); let challenge = challenge.validate().await.unwrap(); let challenge = challenge .wait_done(Duration::from_secs(5), 3) .await .unwrap(); println!("{:#?}", challenge.error); assert_eq!(challenge.status, ChallengeStatus::Valid); let authorization = auth.wait_done(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(authorization.status, AuthorizationStatus::Valid); } assert_eq!(order.status, OrderStatus::Pending); let order = order.wait_ready(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(order.status, OrderStatus::Ready); let pkey = gen_rsa_private_key(4096).unwrap(); let order = order.finalize(Csr::Automatic(pkey)).await.unwrap(); let order = order.wait_done(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(order.status, OrderStatus::Valid); let cert = order.certificate().await.unwrap().unwrap(); assert!(cert.len() > 1); env.stop().await; } #[tokio::test] async fn test_order_http01_challenge_pebble_ec() { let mut env = TestEnv::new("test_order_http01_challenge_pebble_ec"); let testserv = TestServ::new(&mut env).await.unwrap(); let pebble = PebbleBuilder::new() .with_http_port(testserv.http_port) .build(&mut env) .await .unwrap(); let account = pebble_account(&pebble).await; let mut builder = OrderBuilder::new(account); let order = builder .add_dns_identifier("host.docker.internal".to_string()) .build() .await .unwrap(); let authorizations = order.authorizations().await.unwrap(); let client = pebble_http_client().await; for auth in authorizations { let challenge = auth.get_challenge("http-01").unwrap(); assert_eq!(challenge.status, ChallengeStatus::Pending); client .post(format!("{}add-http01", testserv.management_url)) .json(&json!({ "token": challenge.token, "content": challenge.key_authorization().unwrap().unwrap() })) .send() .await .unwrap(); let challenge = challenge.validate().await.unwrap(); let challenge = challenge .wait_done(Duration::from_secs(5), 3) .await .unwrap(); println!("{:#?}", challenge.error); assert_eq!(challenge.status, ChallengeStatus::Valid); let authorization = auth.wait_done(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(authorization.status, AuthorizationStatus::Valid) } assert_eq!(order.status, OrderStatus::Pending); let order = order.wait_ready(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(order.status, OrderStatus::Ready); let pkey = gen_ec_p256_private_key().unwrap(); let order = order.finalize(Csr::Automatic(pkey)).await.unwrap(); let order = order.wait_done(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(order.status, OrderStatus::Valid); let cert = order.certificate().await.unwrap().unwrap(); assert!(cert.len() > 1); env.stop().await; } #[tokio::test] async fn test_order_dns01_challenge_pebble() { let mut env = TestEnv::new("test_order_dns01_challenge_pebble"); let testserv = TestServ::new(&mut env).await.unwrap(); let pebble = PebbleBuilder::new() .with_dns_port(testserv.dns_port) .build(&mut env) .await .unwrap(); let account = pebble_account(&pebble).await; let mut builder = OrderBuilder::new(account); let order = builder .add_dns_identifier("test-order-dns01-challenge-pebble.lcas.dev".to_string()) .build() .await .unwrap(); let authorizations = order.authorizations().await.unwrap(); let client = pebble_http_client().await; for auth in authorizations { let challenge = auth.get_challenge("dns-01").unwrap(); assert_eq!(challenge.status, ChallengeStatus::Pending); client .post(format!("{}set-txt", testserv.management_url)) .json(&json!({ "host": "_acme-challenge.test-order-dns01-challenge-pebble.lcas.dev.", "value": challenge.key_authorization_encoded().unwrap().unwrap(), })) .send() .await .unwrap(); let challenge = challenge.validate().await.unwrap(); let challenge = challenge .wait_done(Duration::from_secs(5), 3) .await .unwrap(); println!("{:#?}", challenge.error); assert_eq!(challenge.status, ChallengeStatus::Valid); let authorization = auth.wait_done(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(authorization.status, AuthorizationStatus::Valid) } assert_eq!(order.status, OrderStatus::Pending); let order = order.wait_ready(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(order.status, OrderStatus::Ready); let pkey = gen_rsa_private_key(4096).unwrap(); let order = order.finalize(Csr::Automatic(pkey)).await.unwrap(); let order = order.wait_done(Duration::from_secs(5), 3).await.unwrap(); assert_eq!(order.status, OrderStatus::Valid); let cert = order.certificate().await.unwrap().unwrap(); assert!(cert.len() > 1); env.stop().await; }