Skip to content

Commit

Permalink
Add: uvicorn ASGI web server when using client certificate auth
Browse files Browse the repository at this point in the history
hypercorn does not implement ASGI TLS Extension which allows to get the
client certificate for the end user.

See pgjones/hypercorn#62.
  • Loading branch information
grydz committed Dec 27, 2024
1 parent df44bf0 commit c2cea04
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dependencies = [
"intel-sgx-ra>=2.3.1,<2.4.0",
"hypercorn[uvloop]>=0.17.3,<0.18.0",
"h2>=4.1.0,<4.2.0",
"uvicorn[standard]>=0.34.0,<1.0.0",
"cenclave-lib-crypto>=1.0.0,<1.1.0"
]
dynamic = ["version"]
Expand Down
31 changes: 28 additions & 3 deletions src/cenclave_lib_sgx/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
from datetime import datetime, timedelta
from enum import Enum
from pathlib import Path
from typing import cast

import uvicorn
from cenclave_lib_crypto.x25519 import x25519_pk_from_sk
from cenclave_lib_crypto.xsalsa20_poly1305 import decrypt_directory
from cryptography import x509
Expand Down Expand Up @@ -56,6 +58,12 @@ def parse_args() -> argparse.Namespace:
type=str,
help="For client certificate authentication (PEM encoded)",
)
parser.add_argument(
"--ssl-verify-mode",
type=int,
help="Either CERT_OPTIONAL (1) or CERT_REQUIRED (2). Default to CERT_REQUIRED.",
default=2,
)
parser.add_argument("--port", type=int, default=443, help="port of the server")
parser.add_argument(
"--subject",
Expand Down Expand Up @@ -245,8 +253,11 @@ def run() -> None:
}

if client_cert := args.client_certificate:
# this mode provides mandatory TLS client cert authentication
config_map["verify_mode"] = int(ssl.CERT_REQUIRED)
config_map["verify_mode"] = (
int(ssl.CERT_OPTIONAL)
if args.ssl_verify_mode == 1
else int(ssl.CERT_REQUIRED)
)
client_cert_path: Path = globs.KEY_DIR_PATH / "client.pem"
client_cert_path.write_text(client_cert)
config_map["ca_certs"] = f"{client_cert_path}"
Expand All @@ -273,4 +284,18 @@ def run() -> None:
application = getattr(importlib.import_module(module_name), application_name)

logging.info("Starting the application (mode=%s)...", ssl_app_mode.name)
asyncio.run(serve(application, config))

if args.client_certificate:
uvicorn.run(
application,
host=f"{args.host}",
port=args.port,
loop="uvloop",
workers=1,
ssl_certfile=cast(Path, config_map["certfile"]),
ssl_keyfile=cast(Path, config_map["keyfile"]),
ssl_ca_certs=cast(str, config_map["ca_certs"]),
ssl_cert_reqs=cast(int, config_map["verify_mode"]),
)
else:
asyncio.run(serve(application, config))

0 comments on commit c2cea04

Please sign in to comment.