Skip to content

gufo.acme.clients.base

An AcmeClient implementation.

AcmeClient

Bases: object

ACME Client.

Examples: Create new account:

async with AcmeClient(directory, key=key) as client:
    uri = await client.new_account("test@example.com")
Sign an CSR:
class SignClient(AcmeClient):
    async def fulfill_http_01(
        self, domain: str, challenge: AcmeChallenge
    ) -> bool:
        # do something useful
        return True

async with SignClient(directory, key=key, account_url=uri) as client:
    cert = await client.sign("example.com", csr)

Attributes:

Name Type Description
JOSE_CONTENT_TYPE str

Content type for JOSE requests.

NONCE_HEADER str

Name of the HTTP response header containing nonce.

RETRY_AFTER_HEADER str

Name of the HTTP reponse header containing required retry delay.

DEFAULT_TIMEOUT float

Default network requests timeout, in seconds.

Parameters:

Name Type Description Default
directory_url str

An URL to ACME directory.

required
key JWK

JWK private key. The compatible key may be generated by the gufo.acme.clients.base.AcmeClient.get_key function.

required
alg Optional[JWASignature]

Signing algorithm to use.

None
account_url Optional[str]

Optional ACME account URL, cotaining the stored result of the previous call to the gufo.acme.clients.base.AcmeClient.new_account function.

None
timeout Optional[float]

Network requests timeout in seconds.

None
user_agent Optional[str]

Override default User-Agent header.

None

__aenter__() async

An asynchronous context manager.

Examples:

async with AcmeClient(....) as client:
    ...

__aexit__(exc_t, exc_v, exc_tb) async

Asynchronous context exit.

clear_challenge(domain, challenge) async

Clear up fulfillment after the challenge has been validated.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

clear_dns_01(domain, challenge) async

Clear up fulfillment after the dns-01 has been validated.

Should be overriden in the subclasses to perform the real job.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

clear_http_01(domain, challenge) async

Clear up fulfillment after the http-01 has been validated.

Should be overriden in the subclasses to perform the real job.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

clear_tls_alpn_01(domain, challenge) async

Clear up fulfillment after the tls-alpn-01 has been validated.

Should be overriden in the subclasses to perform the real job.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

deactivate_account() async

Deactivate account.

Performs RFC-8555 pp. 7.3.6 call to deactivate an account. A deactivated account can no longer request certificate issuance or access resources related to the account, such as orders or authorizations.

To call deactivate_account AcmeClient must be bound to acount either via account_url option or via new_account call. After successfully processing a client will be unbound from account.

Examples:

Deactivate account:

async with AcmeClient(
    directory, key=key,
    account_url=url
) as client:
    uri = await client.deactivate_account()

Raises:

Type Description
AcmeError

In case of the errors.

AcmeNotRegistred

If the client is not bound to account.

decode_auto_base64(data) staticmethod

Decode Base64/Base64 URL.

Auto-detect encoding.

Parameters:

Name Type Description Default
data str

Encoded text.

required

Returns:

Type Description
bytes

Decoded bytes.

finalize_and_wait(order, *, csr) async

Send finalization request and wait for the certificate.

Parameters:

Name Type Description Default
order AcmeOrder

ACME Order.

required
csr bytes

CSR in PEM format.

required

Returns:

Type Description
bytes

Signed certificate in PEM format.

Raises:

Type Description
AcmeCertificateError

When server refuses to sign the certificate.

from_state(state, **kwargs) classmethod

Restore AcmeClient from the state.

Restore the state of client from result of AcmeClient.get_state call.

Parameters:

Name Type Description Default
state bytes

Stored state.

required
kwargs Any

An additional arguments to be passed to constructor.

{}

Returns:

Type Description
CT

New AcmeClient instance.

fulfill_challenge(domain, challenge) async

Try to fulfill challege.

Passes call to underlying fulfill_* function depending on the challenge type.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

Returns:

Name Type Description
True bool

if the challenge is fulfilled.

False bool

when failed to fulfill the challenge.

fulfill_dns_01(domain, challenge) async

Fulfill the dns-01 type of challenge.

Should be overriden in subclasses to perform all necessary jobs. Override clear_dns_01 to perform cleanup.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

Returns:

Name Type Description
True bool

if the challenge is fulfilled.

False bool

when failed to fulfill the challenge.

fulfill_http_01(domain, challenge) async

Fulfill the http-01 type of challenge.

Should be overriden in subclasses to perform all necessary jobs. Override clear_http_01 to perform cleanup.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

Returns:

Name Type Description
True bool

if the challenge is fulfilled.

False bool

when failed to fulfill the challenge.

fulfill_tls_alpn_01(domain, challenge) async

Fulfill the tls-alpn-01 type of challenge.

Should be overriden in subclasses to perform all necessary jobs. Override clear_tls_alpn_01 to perform cleanup.

Parameters:

Name Type Description Default
domain str

Domain name.

required
challenge AcmeChallenge

AcmeChallenge instance.

required

Returns:

Name Type Description
True bool

if the challenge is fulfilled.

False bool

when failed to fulfill the challenge.

get_authorization_status(auth) async

Get an authorization status.

Performs RFC-8555 pp. 7.5 sequence.

Examples:

async with AcmeClient(
    directory,
    key=key,
    account_url=account_url
) as client:
    order = await client.new_order([
        "example.com",
        "sub.example.com"
    ])
    for auth in order.authorizations:
        auth_status = await client.get_authorization_status(auth)

Parameters:

Name Type Description Default
auth AcmeAuthorization

AcmeAuthorization object, usually from AcmeOrder.authorizations.

required

Returns:

Type Description
AcmeAuthorizationStatus

List of AcmeChallenge.

Raises:

Type Description
AcmeError

In case of the errors.

get_domain_csr(domain, private_key) staticmethod

Generate CSR for domain in PEM format.

Parameters:

Name Type Description Default
domain str

Domain name.

required
private_key bytes

Private key in PEM format. get_domain_private_key may be used to generate one.

required

Returns:

Type Description
bytes

CSR in PEM format.

get_domain_private_key(key_size=4096) staticmethod

Generate private key for domain in PEM format.

Parameters:

Name Type Description Default
key_size int

RSA key size.

4096

Returns:

Type Description
bytes

Private key in PEM format.

get_key() staticmethod

Generate account key.

Examples:

key = AcmeClient.get_key()

Returns:

Type Description
JWKRSA

A key which can be used as key parameter to constructor.

get_key_authorization(challenge)

Calculate value for key authorization.

According to RFC-8555 pp. 8.1. Should be used in fulfill_* functions.

Parameters:

Name Type Description Default
challenge AcmeChallenge

ACME challenge.

required

Returns:

Type Description
bytes

content of the key to be returned during challenge.

get_state()

Serialize the state of client to a stream of bytes.

The state will contain all necessasy information to instantiate the new client by the AcmeClient.from_state(...)

Return

State of the client as a stream of bytes

is_bound()

Check if the client is bound to the account.

The client may be bound to account either:

Returns:

Type Description
bool

True - if the client is bound to account, False - otherwise.

new_account(email, *, external_binding=None) async

Create new account.

Performs RFC-8555 pp. 7.3 call to create new account. The account will be bind to the used key.

Examples:

Create an account with single contact email:

async with AcmeClient(directory, key=key) as client:
    uri = await client.new_account("test@example.com")

Create an account with multiple contact emails:

async with AcmeClient(directory, key=key) as client:
    uri = await client.new_account([
        "ca@example.com",
        "boss@example.com"
    ])

Parameters:

Name Type Description Default
email Union[str, Iterable[str]]

String containing email or any iterable yielding emails.

required
external_binding Optional[ExternalAccountBinding]

External account binding, if required.

None

Returns:

Type Description
str

ACME account url which can be passed as account_url parameter to the ACME client.

Raises:

Type Description
AcmeError

In case of the errors.

AcmeAlreadyRegistered

If an client is already bound to account.

AcmeExternalAccountRequred

External account binding is required.

new_order(domain) async

Create new order.

Performs RFC-8555 pp. 7.4 order creation sequence. Before creating a new order any of the prerequisites must be met.

  • new_accout() function called.
  • account_url passed to constructor.

Examples:

Order for single domain:

async with AcmeClient(
    directory,
    key=key,
    account_url=account_url
) as client:
    order = await client.new_order("example.com")

Order for multiple domains:

async with AcmeClient(
    directory,
    key=key,
    account_url=account_url
) as client:
    order = await client.new_order([
        "example.com",
        "sub.example.com"
    ])

Parameters:

Name Type Description Default
domain Union[str, Iterable[str]]

String containing domain or an iterable yielding domains.

required

Returns:

Type Description
AcmeOrder

An AcmeOrder object.

Raises:

Type Description
AcmeError

In case of the errors.

respond_challenge(challenge) async

Respond to challenge.

Responding to challenge means the client performed all fulfillment tasks and ready to prove the challenge.

Parameters:

Name Type Description Default
challenge AcmeChallenge

ACME challenge as returned by get_authorization_status function.

required

sign(domain, csr) async

Sign the CSR and get a certificate for domain.

An orchestration function to perform full ACME sequence, starting from order creation and up to the certificate fetching.

Should be used inn subclasses which override one or more of fulfull_* functions, and, optionaly, clean_* functions.

Examples:

class SignClient(AcmeClient):
    async def fulfill_http_01(
        self, domain: str, challenge: AcmeChallenge
    ) -> bool:
        # do something useful
        return True

async with SignClient(
    directory,
    key=key,
    account_url=uri
) as client:
    cert = await client.sign("example.com", csr)

Returns:

Type Description
bytes

The signed certificate in PEM format.

Raises:

Type Description
AcmeTimeoutError

On timeouts.

AcmeFulfillmentFailed

If the client failed to fulfill any challenge.

AcmeError

and subclasses in case of other errors.

wait_for_authorization(auth) async

Wait untill authorization became valid.

Parameters:

Name Type Description Default
auth AcmeAuthorization

ACME Authorization

required