You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.6 KiB
62 lines
1.6 KiB
from __future__ import annotations |
|
|
|
import secrets |
|
from pathlib import Path |
|
from typing import Dict |
|
|
|
from fastapi import Depends, HTTPException, status |
|
from fastapi.security import HTTPBasic, HTTPBasicCredentials |
|
|
|
|
|
security = HTTPBasic() |
|
|
|
|
|
def verify_basic_auth(config: Dict[str, object], credentials: HTTPBasicCredentials) -> None: |
|
auth_conf = config.get("auth", {}) |
|
expected_username = str(auth_conf.get("username", "")) |
|
expected_password = str(auth_conf.get("password", "")) |
|
|
|
user_ok = secrets.compare_digest(credentials.username, expected_username) |
|
pass_ok = secrets.compare_digest(credentials.password, expected_password) |
|
if not (user_ok and pass_ok): |
|
raise HTTPException( |
|
status_code=status.HTTP_401_UNAUTHORIZED, |
|
detail="Invalid credentials", |
|
headers={"WWW-Authenticate": "Basic"}, |
|
) |
|
|
|
|
|
def ensure_tls_certificate(cert_path: Path, key_path: Path) -> None: |
|
if cert_path.exists() and key_path.exists(): |
|
return |
|
|
|
cert_path.parent.mkdir(parents=True, exist_ok=True) |
|
|
|
import subprocess |
|
|
|
subprocess.run( |
|
[ |
|
"openssl", |
|
"req", |
|
"-x509", |
|
"-nodes", |
|
"-newkey", |
|
"rsa:2048", |
|
"-keyout", |
|
str(key_path), |
|
"-out", |
|
str(cert_path), |
|
"-days", |
|
"3650", |
|
"-subj", |
|
"/CN=pysonnerie.local", |
|
], |
|
check=True, |
|
) |
|
|
|
|
|
def make_auth_dependency(get_config): |
|
def auth_dependency(credentials: HTTPBasicCredentials = Depends(security)) -> None: |
|
verify_basic_auth(get_config(), credentials) |
|
|
|
return auth_dependency
|
|
|