z230
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# janssenpc_file_receive_v1.2
|
||||
|
||||
Stáhne soubory čekající na serveru `msgs.buzalka.cz` do `##JNJPrenos\ZHovorcovic\`.
|
||||
Spouští se ručně na JNJ stroji dle potřeby.
|
||||
|
||||
## Spuštění (JNJ stroj)
|
||||
```
|
||||
C:\Users\vbuzalka\OneDrive - JNJ\##JNJPrenos\Python\python.exe "C:\Users\vbuzalka\OneDrive - JNJ\##JNJPrenos\Python\janssenpc_file_receive_v1.2.py"
|
||||
```
|
||||
(cestu ke skriptu případně upravit podle skutečného umístění)
|
||||
|
||||
## Princip
|
||||
1. `GET /status` → seznam Fernet tokenů (zašifrovaná jména souborů ve frontě
|
||||
Dropbox `UploadToJNJ`). Zscaler vidí jen neprůhledné řetězce.
|
||||
2. Pro každý token `GET /item/{token}` s hlavičkou `Accept: application/json`
|
||||
→ server (app.py >= v2.3) vrátí `{"data": "<fernet_b64>"}`.
|
||||
3. Klient dešifruje `data` (Fernet z TOKENu) → obsah souboru; jméno získá
|
||||
dešifrováním tokenu. Uloží do `ZHovorcovic\` (zamčený soubor → ` (2)` atd.).
|
||||
4. Server po vydání souboru přesouvá originál do `UploadToJNJ/##Trash/`.
|
||||
|
||||
## Proč JSON (v1.2)
|
||||
Korporátní filtr (Zscaler/SiteMinder) blokoval binární downloady — při prvním
|
||||
stažení PDF si odpověď zachytil, sám si zkusil soubor stáhnout znovu (na serveru
|
||||
viditelné jako druhý GET bez auth → 401) a klientovi vrátil
|
||||
`403 Forbidden` + redirect s `?_sm_nck=1`. JSON odpověď (`application/json`)
|
||||
AV sandbox na přílohy nespouští.
|
||||
|
||||
## Vazby
|
||||
- Server: `EmailsImport/DockerCustomApp/app.py` v2.3 (endpoint `/item` — JSON při
|
||||
`Accept: application/json`, jinak binárka pro starší klienty).
|
||||
- Protějšek pro upload: `janssenpc_file_watch.py` / `janssenpc_file_send`.
|
||||
|
||||
## Historie
|
||||
- v1.2 (2026-06-10): přenos obsahu jako JSON (bypass AV sandboxu filtru)
|
||||
- v1.1 (2026-06-08): jména souborů jako Fernet tokeny v URL (bypass DLP)
|
||||
- v1.0: první verze
|
||||
@@ -0,0 +1,105 @@
|
||||
# Název: janssenpc_file_receive_v1.2.py
|
||||
# Verze: 1.2
|
||||
# Datum: 2026-06-10
|
||||
# Popis: Stáhne soubory čekající na serveru (msgs.buzalka.cz) do ##JNJPrenos\ZHovorcovic\.
|
||||
# Spouštět ručně dle potřeby.
|
||||
#
|
||||
# Změna v1.2:
|
||||
# Obsah souboru se přenáší jako JSON ({"data": fernet_b64}), ne jako binární
|
||||
# příloha — korporátní filtr (403 + ?_sm_nck=1) blokoval binární downloady
|
||||
# (AV sandbox na "file download"); JSON odpověď inspekci příloh nespouští.
|
||||
# Klient posílá Accept: application/json; server (app.py >= v2.3) podle toho
|
||||
# volí formát, starý binární režim zůstává pro v1.1.
|
||||
#
|
||||
# Změna v1.1:
|
||||
# Jména souborů ze /status jsou Fernet tokeny (zašifrované původní názvy).
|
||||
# Klient je pošle beze změny jako URL token do /item/{token} — Zscaler vidí
|
||||
# jen neprůhledný řetězec, ne skutečné jméno souboru (bypass DLP).
|
||||
# Po stažení a dešifrování obsahu klient dešifruje i token → původní jméno → uloží.
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import requests
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from cryptography.fernet import Fernet
|
||||
|
||||
TOKEN = "13e1bb01-9fd5-44a8-8ce9-4ee27133d340"
|
||||
PENDING_URL = "https://msgs.buzalka.cz/status"
|
||||
DOWNLOAD_URL = "https://msgs.buzalka.cz/item"
|
||||
RECEIVE_DIR = Path(r"C:\Users\vbuzalka\OneDrive - JNJ\##JNJPrenos\ZHovorcovic")
|
||||
LOG_FILE = Path(__file__).parent / "file_send.log"
|
||||
_FERNET = Fernet(base64.urlsafe_b64encode(hashlib.sha256(TOKEN.encode()).digest()))
|
||||
|
||||
|
||||
def log(msg: str):
|
||||
ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
line = f"[{ts}] {msg}"
|
||||
print(line)
|
||||
with LOG_FILE.open("a", encoding="utf-8") as lf:
|
||||
lf.write(line + "\n")
|
||||
|
||||
|
||||
def resolve_dest(directory: Path, filename: str) -> Path:
|
||||
"""Přepíše existující soubor, pokud je zamčený → name (2), (3)..."""
|
||||
dest = directory / filename
|
||||
if not dest.exists():
|
||||
return dest
|
||||
try:
|
||||
dest.open('r+b').close()
|
||||
return dest
|
||||
except PermissionError:
|
||||
pass
|
||||
stem = Path(filename).stem
|
||||
suffix = Path(filename).suffix
|
||||
n = 2
|
||||
while True:
|
||||
candidate = directory / f"{stem} ({n}){suffix}"
|
||||
if not candidate.exists():
|
||||
return candidate
|
||||
try:
|
||||
candidate.open('r+b').close()
|
||||
return candidate
|
||||
except PermissionError:
|
||||
n += 1
|
||||
|
||||
|
||||
log("=== file_receive: Spuštění ===")
|
||||
|
||||
try:
|
||||
resp = requests.get(PENDING_URL, headers={"Authorization": f"Bearer {TOKEN}"}, timeout=30)
|
||||
resp.raise_for_status()
|
||||
pending = resp.json().get("files", []) # seznam Fernet tokenů
|
||||
log(f"Souborů čeká na serveru: {len(pending)}")
|
||||
except Exception as e:
|
||||
log(f"CHYBA při dotazu na server: {e}")
|
||||
pending = []
|
||||
|
||||
if pending:
|
||||
RECEIVE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
for enc_token in pending:
|
||||
# Dešifruj token → původní jméno souboru (pro log + uložení)
|
||||
try:
|
||||
orig_filename = _FERNET.decrypt(enc_token.encode()).decode()
|
||||
except Exception as e:
|
||||
log(f" CHYBA (dešifrování jména) | {enc_token[:20]}... | {e}")
|
||||
continue
|
||||
|
||||
try:
|
||||
r = requests.get(
|
||||
f"{DOWNLOAD_URL}/{enc_token}",
|
||||
headers={
|
||||
"Authorization": f"Bearer {TOKEN}",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
timeout=120,
|
||||
)
|
||||
r.raise_for_status()
|
||||
decrypted = _FERNET.decrypt(r.json()["data"].encode())
|
||||
dest = resolve_dest(RECEIVE_DIR, orig_filename)
|
||||
dest.write_bytes(decrypted)
|
||||
log(f" STAŽENO | {orig_filename}{' → ' + dest.name if dest.name != orig_filename else ''}")
|
||||
except Exception as e:
|
||||
log(f" CHYBA | {orig_filename} | {e}")
|
||||
|
||||
log("=== file_receive: Hotovo ===")
|
||||
Reference in New Issue
Block a user