security
This commit is contained in:
parent
3af3431da4
commit
62dd1819cb
107
app/security.py
107
app/security.py
@ -5,7 +5,11 @@ import hmac
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from fastapi import HTTPException, Security, status
|
||||
from fastapi import (
|
||||
HTTPException,
|
||||
Security,
|
||||
status,
|
||||
)
|
||||
from fastapi.security import (
|
||||
APIKeyHeader,
|
||||
HTTPAuthorizationCredentials,
|
||||
@ -19,6 +23,21 @@ SEARCH_API_KEY_HEADER = "X-API-Key"
|
||||
SYNC_API_KEY_HEADER = "X-API-Key"
|
||||
|
||||
|
||||
TRUE_ENV_VALUES = {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
}
|
||||
|
||||
FALSE_ENV_VALUES = {
|
||||
"0",
|
||||
"false",
|
||||
"no",
|
||||
"off",
|
||||
}
|
||||
|
||||
|
||||
search_api_key_scheme = APIKeyHeader(
|
||||
name=SEARCH_API_KEY_HEADER,
|
||||
scheme_name="SearchApiKey",
|
||||
@ -87,7 +106,26 @@ def expected_gitea_repository() -> str:
|
||||
"EXPECTED_GITEA_REPOSITORY"
|
||||
)
|
||||
|
||||
if "/" not in value:
|
||||
parts = value.split(
|
||||
"/"
|
||||
)
|
||||
|
||||
if len(parts) != 2:
|
||||
raise RuntimeError(
|
||||
"EXPECTED_GITEA_REPOSITORY musí mať "
|
||||
"tvar vlastník/repozitár"
|
||||
)
|
||||
|
||||
owner, repository = parts
|
||||
|
||||
if (
|
||||
not owner
|
||||
or not repository
|
||||
or any(
|
||||
character.isspace()
|
||||
for character in value
|
||||
)
|
||||
):
|
||||
raise RuntimeError(
|
||||
"EXPECTED_GITEA_REPOSITORY musí mať "
|
||||
"tvar vlastník/repozitár"
|
||||
@ -102,26 +140,53 @@ def webhook_should_pull_git() -> bool:
|
||||
"false",
|
||||
).strip().casefold()
|
||||
|
||||
return value in {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
}
|
||||
if value in TRUE_ENV_VALUES:
|
||||
return True
|
||||
|
||||
if value in FALSE_ENV_VALUES:
|
||||
return False
|
||||
|
||||
raise RuntimeError(
|
||||
"WEBHOOK_PULL_GIT musí byť boolean "
|
||||
"hodnota true/false"
|
||||
)
|
||||
|
||||
|
||||
def validate_security_configuration() -> None:
|
||||
validate_secret(
|
||||
webhook_secret = validate_secret(
|
||||
"WEBHOOK_SECRET"
|
||||
)
|
||||
validate_secret(
|
||||
|
||||
sync_api_key = validate_secret(
|
||||
"SYNC_API_KEY"
|
||||
)
|
||||
validate_secret(
|
||||
|
||||
search_api_key = validate_secret(
|
||||
"SEARCH_API_KEY"
|
||||
)
|
||||
|
||||
# Každá funkcia musí používať vlastný
|
||||
# credential. Jeden uniknutý secret tak
|
||||
# neposkytne prístup ku všetkým operáciám.
|
||||
if len(
|
||||
{
|
||||
webhook_secret,
|
||||
sync_api_key,
|
||||
search_api_key,
|
||||
}
|
||||
) != 3:
|
||||
raise RuntimeError(
|
||||
"WEBHOOK_SECRET, SYNC_API_KEY "
|
||||
"a SEARCH_API_KEY musia byť "
|
||||
"navzájom rozdielne"
|
||||
)
|
||||
|
||||
expected_gitea_repository()
|
||||
|
||||
# Validujeme aj voliteľnú boolean
|
||||
# konfiguráciu už pri štarte aplikácie.
|
||||
webhook_should_pull_git()
|
||||
|
||||
|
||||
def require_search_api_key(
|
||||
api_key: str | None = Security(
|
||||
@ -272,14 +337,17 @@ def repository_name_from_payload(
|
||||
):
|
||||
return None
|
||||
|
||||
value = (
|
||||
repository.get(
|
||||
# Pri webhooku akceptujeme iba
|
||||
# jednoznačný Gitea full_name:
|
||||
#
|
||||
# vlastník/repozitár
|
||||
#
|
||||
# Samotné "name" nestačí, pretože
|
||||
# rovnaký názov môže existovať pod
|
||||
# rôznymi vlastníkmi.
|
||||
value = repository.get(
|
||||
"full_name"
|
||||
)
|
||||
or repository.get(
|
||||
"name"
|
||||
)
|
||||
)
|
||||
|
||||
if not isinstance(
|
||||
value,
|
||||
@ -297,7 +365,6 @@ def same_repository(
|
||||
expected: str,
|
||||
) -> bool:
|
||||
return hmac.compare_digest(
|
||||
actual.casefold(),
|
||||
expected.casefold(),
|
||||
actual.strip().casefold(),
|
||||
expected.strip().casefold(),
|
||||
)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user