acumen/challenge
Challenge types for ACME domain validation.
After creating an order, complete challenges to prove control over the requested identifiers.
Types
An ACME challenge for domain validation.
Each variant represents a specific challenge type with its required fields. Unknown challenge types are ignored during decoding.
pub type Challenge {
Http01Challenge(
url: url.Url,
status: Status,
token: String,
validated: option.Option(timestamp.Timestamp),
error: option.Option(acumen.AcmeError),
)
Dns01Challenge(
url: url.Url,
status: Status,
token: String,
validated: option.Option(timestamp.Timestamp),
error: option.Option(acumen.AcmeError),
)
TlsAlpn01Challenge(
url: url.Url,
status: Status,
token: String,
validated: option.Option(timestamp.Timestamp),
error: option.Option(acumen.AcmeError),
)
DnsAccount01Challenge(
url: url.Url,
status: Status,
token: String,
validated: option.Option(timestamp.Timestamp),
error: option.Option(acumen.AcmeError),
)
DnsPersist01Challenge(
url: url.Url,
status: Status,
validated: option.Option(timestamp.Timestamp),
error: option.Option(acumen.AcmeError),
issuer_domain_names: List(String),
)
}
Constructors
-
Http01Challenge( url: url.Url, status: Status, token: String, validated: option.Option(timestamp.Timestamp), error: option.Option(acumen.AcmeError), )HTTP-01: serve a file at
/.well-known/acme-challenge/{token}. -
Dns01Challenge( url: url.Url, status: Status, token: String, validated: option.Option(timestamp.Timestamp), error: option.Option(acumen.AcmeError), )DNS-01: create a TXT record at
_acme-challenge.{domain}. -
TlsAlpn01Challenge( url: url.Url, status: Status, token: String, validated: option.Option(timestamp.Timestamp), error: option.Option(acumen.AcmeError), )TLS-ALPN-01: respond to the
acme-tls/1ALPN protocol. -
DnsAccount01Challenge( url: url.Url, status: Status, token: String, validated: option.Option(timestamp.Timestamp), error: option.Option(acumen.AcmeError), )DNS-Account-01: create an account-scoped DNS TXT record.
-
DnsPersist01Challenge( url: url.Url, status: Status, validated: option.Option(timestamp.Timestamp), error: option.Option(acumen.AcmeError), issuer_domain_names: List(String), )DNS-Persist-01: create a persistent TXT record at
_validation-persist.{domain}.
Known ACME challenge types for use with find_by_type.
pub type ChallengeType {
Http01
Dns01
TlsAlpn01
DnsPersist01
DnsAccount01
}
Constructors
-
Http01HTTP-01 challenge type.
-
Dns01DNS-01 challenge type.
-
TlsAlpn01TLS-ALPN-01 challenge type.
-
DnsPersist01DNS-Persist-01 challenge type.
-
DnsAccount01DNS-Account-01 challenge type.
Values
pub fn dns01_txt_record(
key_authorization: String,
) -> Result(String, acumen.AcmeError)
Computes the DNS-01 TXT record value.
Example
let assert Ok(key_auth) = challenge.key_authorization(dns_challenge, registered_key)
let assert Ok(txt_value) = challenge.dns01_txt_record(key_auth)
// Create TXT record: _acme-challenge.example.com -> txt_value
pub fn dns_account01_txt_record(
for domain: String,
account_url account_url: url.Url,
key_authorization key_authorization: String,
) -> Result(#(String, String), acumen.AcmeError)
Computes the DNS-Account-01 TXT record name and value.
Returns #(name, value) where name is the full record name and
value is the record content.
Example
let assert Ok(key_auth) = challenge.key_authorization(dns_acct_challenge, registered_key)
let assert Ok(#(record_name, record_value)) =
challenge.dns_account01_txt_record("example.com", registered_key.kid, key_auth)
// Create TXT record: record_name -> record_value
pub fn dns_persist01_txt_record(
issuer issuer_domain_name: String,
account_url account_url: url.Url,
) -> String
Builds a DNS-Persist-01 TXT record value for a single issuer.
A DNS-Persist-01 challenge may include multiple issuer domain names.
Callers should create a separate TXT record for each issuer, all on the
same _validation-persist.{domain} DNS name.
Example
let assert Ok(issuers) = challenge.issuer_domain_names(dns_persist_challenge)
let txt_records = list.map(issuers, fn(issuer) {
challenge.dns_persist01_txt_record(issuer:, account_url: registered_key.kid)
})
// Create a TXT record at _validation-persist.example.com for each value
pub fn find_by_type(
challenges: List(Challenge),
of type_: ChallengeType,
) -> Result(Challenge, Nil)
Finds the first challenge matching the given type, or Error(Nil) if none.
Example
let assert Ok(http_challenge) =
challenge.find_by_type(authorization.challenges, of: challenge.Http01)
pub fn issuer_domain_names(
challenge: Challenge,
) -> Result(List(String), Nil)
Returns the issuer domain names for a DNS-Persist-01 challenge.
Returns Error(Nil) for other challenge types.
pub fn key_authorization(
challenge: Challenge,
key: acumen.RegisteredKey,
) -> Result(String, acumen.AcmeError)
Computes the key authorization string for a challenge.
Returns Error(acumen.InvalidChallenge(_)) for challenge types that
don’t have a token (e.g., DnsPersist01Challenge).
Example
let assert Ok(key_auth) = challenge.key_authorization(http_challenge, registered_key)
// Deploy: GET /.well-known/acme-challenge/{token} -> key_auth
pub fn token(challenge: Challenge) -> Result(String, Nil)
Returns the token for a challenge.
Returns Error(Nil) for challenge types without a token (e.g. DNS-Persist-01).