-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
155 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# --------------------------------------------------------------------- | ||
# Gufo ACME: WebACMEClient implementation | ||
# --------------------------------------------------------------------- | ||
# Copyright (C) 2023, Gufo Labs | ||
# --------------------------------------------------------------------- | ||
"""A WebACMEClient implementation.""" | ||
|
||
# Python modules | ||
import os | ||
from pathlib import Path | ||
from typing import Any, Union | ||
|
||
# Gufo ACME modules | ||
from ..log import logger | ||
from ..types import ACMEChallenge | ||
from .base import ACMEClient | ||
|
||
|
||
class WebACMEClient(ACMEClient): | ||
""" | ||
A webserver-backed ACME client. | ||
Fulfills http-01 challenge by creating | ||
and removing token files in predefined | ||
directories. | ||
Args: | ||
path: Path mapped to /.well-known/acme-challenges | ||
directory. | ||
""" | ||
|
||
def __init__( | ||
self: "WebACMEClient", | ||
directory_url: str, | ||
*, | ||
path: Union[str, Path], | ||
**kwargs: Any, | ||
) -> None: | ||
super().__init__(directory_url, **kwargs) | ||
self.path = Path(path) | ||
|
||
def _get_path(self: "WebACMEClient", challenge: ACMEChallenge) -> Path: | ||
""" | ||
Get Path for challenge. | ||
Args: | ||
challenge: ACME challenge | ||
Returns: | ||
token path. | ||
""" | ||
return self.path / Path(challenge.token) | ||
|
||
async def fulfill_http_01( | ||
self: "WebACMEClient", domain: str, challenge: ACMEChallenge | ||
) -> bool: | ||
""" | ||
Perform http-01 fullfilment. | ||
Put token to <path>/<token> file. | ||
Args: | ||
domain: Domain name | ||
challenge: ACMEChallenge instance, containing token. | ||
Returns: | ||
True - on succeess | ||
Raises: | ||
ACMEFulfillmentFailed: On error. | ||
""" | ||
path = self._get_path(challenge) | ||
v = self.get_key_authorization(challenge) | ||
logger.warning("Writing token to %s", path) | ||
with open(path, "wb") as fp: | ||
fp.write(v) | ||
return True | ||
|
||
async def clear_http_01( | ||
self: "WebACMEClient", domain: str, challenge: ACMEChallenge | ||
) -> None: | ||
""" | ||
Remove provisioned token. | ||
Args: | ||
domain: Domain name | ||
challenge: ACMEChallenge instance, containing token. | ||
Raises: | ||
ACMEFulfillmentFailed: On error. | ||
""" | ||
path = self._get_path(challenge) | ||
if os.path.exists(path): | ||
logger.warning("Removing token from %s", path) | ||
os.unlink(path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Python modules | ||
import asyncio | ||
import os | ||
import tempfile | ||
from pathlib import Path | ||
|
||
# Gufo ACMEE modules | ||
from gufo.acme.clients.web import WebACMEClient | ||
from gufo.acme.types import ACMEChallenge | ||
|
||
from .utils import DIRECTORY, KEY | ||
|
||
DOMAIN = "example.com" | ||
AUTH_KEY = ( | ||
b"qPsDhTbvumL6q2DryepIyzJS1nMkghS92IqI4mug-7c.IoRaMHpsTJikEnDg70XhS0d7Xx1ZU3Tz" | ||
b"MzhTKFITfwY" | ||
) | ||
|
||
|
||
def test_web() -> None: | ||
async def inner(): | ||
chall = ACMEChallenge( | ||
type="http-01", | ||
url="xxx", | ||
token="qPsDhTbvumL6q2DryepIyzJS1nMkghS92IqI4mug-7c", | ||
) | ||
with tempfile.TemporaryDirectory() as tmp: | ||
path = Path(tmp) | ||
client = WebACMEClient(DIRECTORY, key=KEY, path=path) | ||
r = await client.fulfill_http_01(DOMAIN, chall) | ||
assert r is True | ||
with open(path / chall.token, "rb") as fp: | ||
data = fp.read() | ||
assert data == AUTH_KEY | ||
await client.clear_http_01(DOMAIN, chall) | ||
assert not os.path.exists(path / Path(chall.token)) | ||
|
||
asyncio.run(inner()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters