{"id":19562681,"url":"https://github.com/jamsocket/acme2-eab","last_synced_at":"2026-01-25T16:32:54.619Z","repository":{"id":226825280,"uuid":"769733058","full_name":"jamsocket/acme2-eab","owner":"jamsocket","description":null,"archived":false,"fork":false,"pushed_at":"2024-09-11T16:19:58.000Z","size":256,"stargazers_count":4,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-13T19:23:30.766Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamsocket.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-09T22:35:04.000Z","updated_at":"2025-10-08T13:50:32.000Z","dependencies_parsed_at":"2024-09-11T23:10:21.438Z","dependency_job_id":"c3ab8318-a43f-4b97-a003-60ec24e9202d","html_url":"https://github.com/jamsocket/acme2-eab","commit_stats":{"total_commits":55,"total_committers":7,"mean_commits":7.857142857142857,"dds":0.509090909090909,"last_synced_commit":"a0fbc955ccdc8255da37b17b27a395523817c724"},"previous_names":["paulgb/acme2"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/jamsocket/acme2-eab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamsocket%2Facme2-eab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamsocket%2Facme2-eab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamsocket%2Facme2-eab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamsocket%2Facme2-eab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamsocket","download_url":"https://codeload.github.com/jamsocket/acme2-eab/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamsocket%2Facme2-eab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28755557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T16:32:25.380Z","status":"ssl_error","status_checked_at":"2026-01-25T16:32:09.189Z","response_time":113,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T05:15:21.607Z","updated_at":"2026-01-25T16:32:54.602Z","avatar_url":"https://github.com/jamsocket.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Note: this is a fork of [lucacasonato/acme2](https://github.com/lucacasonato/acme2) that adds [External Account Binding](https://dev.digicert.com/services-api/api-keys/acme-external-account-binding/)\nsupport, needed for ZeroSSL and Google Certificate Manager support. It is packaged separately so that we can use it from other codebases until [this upstream PR](https://github.com/lucacasonato/acme2/pull/21)\nis merged.\n\n# acme2\n\nA [Tokio](https://crates.io/crates/tokio) and\n[OpenSSL](https://crates.io/crates/openssl) based\n[ACMEv2](https://tools.ietf.org/html/rfc8555) client.\n\nFeatures:\n\n- ACME v2 support, tested against Let's Encrypt and Pebble\n- Fully async, using `reqwest` / Tokio\n- Support for DNS01 and HTTP01 validation\n- Fully instrumented with `tracing`\n\n## Example\n\nThis example demonstrates how to provision a certificate for the domain\n`example.com` using `http-01` validation.\n\n```rust\nuse acme2::gen_rsa_private_key;\nuse acme2::AccountBuilder;\nuse acme2::AuthorizationStatus;\nuse acme2::ChallengeStatus;\nuse acme2::DirectoryBuilder;\nuse acme2::Error;\nuse acme2::OrderBuilder;\nuse acme2::OrderStatus;\nuse acme2::Csr;\nuse std::time::Duration;\n\nconst LETS_ENCRYPT_URL: \u0026'static str =\n  \"https://acme-v02.api.letsencrypt.org/directory\";\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Error\u003e {\n  // Create a new ACMEv2 directory for Let's Encrypt.\n  let dir = DirectoryBuilder::new(LETS_ENCRYPT_URL.to_string())\n    .build()\n    .await?;\n\n  // Create an ACME account to use for the order. For production\n  // purposes, you should keep the account (and private key), so\n  // you can renew your certificate easily.\n  let mut builder = AccountBuilder::new(dir.clone());\n  builder.contact(vec![\"mailto:hello@lcas.dev\".to_string()]);\n  builder.terms_of_service_agreed(true);\n  let account = builder.build().await?;\n\n  // Create a new order for a specific domain name.\n  let mut builder = OrderBuilder::new(account);\n  builder.add_dns_identifier(\"example.com\".to_string());\n  let order = builder.build().await?;\n\n  // Get the list of needed authorizations for this order.\n  let authorizations = order.authorizations().await?;\n  for auth in authorizations {\n    // Get an http-01 challenge for this authorization (or panic\n    // if it doesn't exist).\n    let challenge = auth.get_challenge(\"http-01\").unwrap();\n\n    // At this point in time, you must configure your webserver to serve\n    // a file at `https://example.com/.well-known/${challenge.token}`\n    // with the content of `challenge.key_authorization()??`.\n\n    // Start the validation of the challenge.\n    let challenge = challenge.validate().await?;\n\n    // Poll the challenge every 5 seconds until it is in either the\n    // `valid` or `invalid` state.\n    let challenge = challenge.wait_done(Duration::from_secs(5), 3).await?;\n\n    assert_eq!(challenge.status, ChallengeStatus::Valid);\n\n    // You can now remove the challenge file hosted on your webserver.\n\n    // Poll the authorization every 5 seconds until it is in either the\n    // `valid` or `invalid` state.\n    let authorization = auth.wait_done(Duration::from_secs(5), 3).await?;\n    assert_eq!(authorization.status, AuthorizationStatus::Valid)\n  }\n\n  // Poll the order every 5 seconds until it is in either the\n  // `ready` or `invalid` state. Ready means that it is now ready\n  // for finalization (certificate creation).\n  let order = order.wait_ready(Duration::from_secs(5), 3).await?;\n\n  assert_eq!(order.status, OrderStatus::Ready);\n\n  // Generate an RSA private key for the certificate.\n  let pkey = gen_rsa_private_key(4096)?;\n\n  // Create a certificate signing request for the order, and request\n  // the certificate.\n  let order = order.finalize(Csr::Automatic(pkey)).await?;\n\n  // Poll the order every 5 seconds until it is in either the\n  // `valid` or `invalid` state. Valid means that the certificate\n  // has been provisioned, and is now ready for download.\n  let order = order.wait_done(Duration::from_secs(5), 3).await?;\n\n  assert_eq!(order.status, OrderStatus::Valid);\n\n  // Download the certificate, and panic if it doesn't exist.\n  let cert = order.certificate().await?.unwrap();\n  assert!(cert.len() \u003e 1);\n\n  Ok(())\n}\n```\n\n## Development\n\nTo run the tests, you will need a running Docker instance. Then, run:\n\n```\ncargo test\n```\n\n## Licence\n\nThis project is licenced under MIT. See LICENCE file for more.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamsocket%2Facme2-eab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamsocket%2Facme2-eab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamsocket%2Facme2-eab/lists"}