fix
This commit is contained in:
+30
-3
@@ -1,9 +1,36 @@
|
|||||||
DEPLOY_SCRIPT = "/tools/deploy-app.sh"
|
DEPLOY_SCRIPT = "/tools/deploy-app.sh"
|
||||||
|
|
||||||
|
# Holé názvy shell skriptů, které smí Portál zařadit jako Worker run_script job.
|
||||||
|
# Worker přijímá v poli script_name jen HOLÝ název bez cesty (adresář scripts/ si doplní sám)
|
||||||
|
# a cokoli s cestou ("scripts/...", "../...", absolutní cesta) odmítne hláškou
|
||||||
|
# "Invalid script name". Stejné pravidlo má i portál sám v
|
||||||
|
# app/routes/scheduled_scripts.validate_script_name. Tuto množinu validujeme i tady, ať
|
||||||
|
# nezaložíme job, který Worker stejně zahodí (přesně na tom padal job 221).
|
||||||
|
ALLOWED_WORKER_SCRIPTS = {
|
||||||
|
"deploy-app.sh",
|
||||||
|
"delete-app.sh",
|
||||||
|
"deploy-core-service.sh",
|
||||||
|
"generate-caddyfile.sh",
|
||||||
|
"redeploy-enabled-apps.sh",
|
||||||
|
"backup-appfactory.sh",
|
||||||
|
}
|
||||||
|
|
||||||
# Mazání aplikace NEPROVÁDÍ portál přímo – běží bez práv k workspace, takže rm padá na
|
# Mazání aplikace NEPROVÁDÍ portál přímo – běží bez práv k workspace, takže rm padá na
|
||||||
# "Permission denied". Portál jen zařadí run_script job a Worker spustí tento skript
|
# "Permission denied". Portál jen zařadí run_script job a Worker spustí tento skript
|
||||||
# v appfactory-tools s právy serveru. Prefix "scripts/" je povinný, jinak ho worker hledá
|
# v appfactory-tools/scripts/ s právy serveru.
|
||||||
# ve špatné složce (stejná konvence jako app/routes/runtime.py).
|
# POZOR: holý název, NE "scripts/delete-app.sh" – cesta v názvu = "Invalid script name".
|
||||||
DELETE_APP_SCRIPT_NAME = "scripts/delete-app.sh"
|
DELETE_APP_SCRIPT_NAME = "delete-app.sh"
|
||||||
|
|
||||||
|
|
||||||
|
def is_allowed_worker_script(script_name: str) -> bool:
|
||||||
|
"""True jen pro holý, povolený název skriptu pro Worker run_script job.
|
||||||
|
Odmítne prázdný název, název nekončící .sh, název s cestou ("/", "\\", "..") i název
|
||||||
|
mimo allowlist – tedy přesně případy, na které Worker hlásí "Invalid script name"."""
|
||||||
|
if not script_name or not script_name.endswith(".sh"):
|
||||||
|
return False
|
||||||
|
if "/" in script_name or "\\" in script_name or ".." in script_name:
|
||||||
|
return False
|
||||||
|
return script_name in ALLOWED_WORKER_SCRIPTS
|
||||||
BACKUP_SCRIPT = "/tools/backup-appfactory.sh"
|
BACKUP_SCRIPT = "/tools/backup-appfactory.sh"
|
||||||
RESTORE_SCRIPT = "/tools/restore-appfactory.sh"
|
RESTORE_SCRIPT = "/tools/restore-appfactory.sh"
|
||||||
GENERATE_COMPOSE_SCRIPT = "/tools/generate-apps-compose.sh"
|
GENERATE_COMPOSE_SCRIPT = "/tools/generate-apps-compose.sh"
|
||||||
|
|||||||
+29
-4
@@ -13,6 +13,7 @@ from ..config import (
|
|||||||
GENERATE_COMPOSE_SCRIPT,
|
GENERATE_COMPOSE_SCRIPT,
|
||||||
get_appfactory_host,
|
get_appfactory_host,
|
||||||
get_gitea_public_url,
|
get_gitea_public_url,
|
||||||
|
is_allowed_worker_script,
|
||||||
read_env_value,
|
read_env_value,
|
||||||
)
|
)
|
||||||
from ..db.apps import (
|
from ..db.apps import (
|
||||||
@@ -1520,10 +1521,34 @@ def create_app(
|
|||||||
|
|
||||||
@router.post("/delete-app", response_class=HTMLResponse)
|
@router.post("/delete-app", response_class=HTMLResponse)
|
||||||
def delete_app(app_id: str = Form(...), user=Depends(require_admin)):
|
def delete_app(app_id: str = Form(...), user=Depends(require_admin)):
|
||||||
# Portál NEMAŽE workspace přímo – nemá k němu práva (rm padá na "Permission denied").
|
# Portál NEMAŽE workspace/container/image/gitea repo přímo – běží bez práv k workspace,
|
||||||
# Místo toho zařadí run_script job; mazání (container, image, gitea repo, workspace)
|
# takže rm padá na "Permission denied". Místo toho jen zařadí run_script job a mazání
|
||||||
# provede Worker přes scripts/delete-app.sh s právy serveru. Veškerá runtime/Docker
|
# provede Worker přes delete-app.sh s právy serveru. Veškerá runtime/Docker logika patří
|
||||||
# logika patří do Workeru a shell skriptů, ne do portálu.
|
# do Workeru a shell skriptů, ne do portálu.
|
||||||
|
#
|
||||||
|
# KONTRAKT NÁZVU AKCE (proč dříve padalo "Invalid script name"):
|
||||||
|
# - do jobu se ukládá HOLÝ název skriptu: script_name = "delete-app.sh"
|
||||||
|
# (stejný formát jako ostatní run_script joby, viz preflight-check.sh / bootstrap-v2.sh
|
||||||
|
# a portálová validace v scheduled_scripts.validate_script_name);
|
||||||
|
# - Worker přijímá jen holý název, adresář scripts/ si doplní sám, a cokoli s cestou
|
||||||
|
# ("scripts/delete-app.sh", "../...", absolutní cesta) odmítne jako "Invalid script name".
|
||||||
|
# Job 221 padal právě proto, že se posílalo "scripts/delete-app.sh" (název s cestou).
|
||||||
|
# Stejný allowlist/validaci děláme i tady, ať portál nikdy nezaloží job, který Worker zahodí.
|
||||||
|
if not is_allowed_worker_script(DELETE_APP_SCRIPT_NAME):
|
||||||
|
return render_result(
|
||||||
|
title="Smazání služby: CHYBA",
|
||||||
|
back_url="/portal/apps",
|
||||||
|
sections=[
|
||||||
|
(
|
||||||
|
"Chyba",
|
||||||
|
f"Neplatný název skriptu pro Worker job: '{DELETE_APP_SCRIPT_NAME}'. "
|
||||||
|
"Musí to být holý povolený název bez cesty (např. 'delete-app.sh'), jinak "
|
||||||
|
"Worker job odmítne hláškou 'Invalid script name'. Job nebyl vytvořen.",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
user=user,
|
||||||
|
)
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"script_name": DELETE_APP_SCRIPT_NAME,
|
"script_name": DELETE_APP_SCRIPT_NAME,
|
||||||
"args": [app_id],
|
"args": [app_id],
|
||||||
|
|||||||
Reference in New Issue
Block a user