fix: prevent passphrase prompt hang in Docker by closing stdin and detecting encrypted keys

Added stdin=subprocess.DEVNULL to OCI CLI subprocess call so it fails fast
instead of hanging when a passphrase prompt would occur. Added detection of
encrypted PEM keys at upload time — rejects with clear error message if
passphrase is missing. Improved error message when passphrase-related
errors are detected during test.
This commit is contained in:
nogueiraguh
2026-03-03 16:09:45 -03:00
parent 0ca60fb017
commit 880c26530c

View File

@@ -399,7 +399,15 @@ async def save_oci(
):
cid = str(uuid.uuid4()); cdir = OCI_DIR / cid; cdir.mkdir(parents=True)
kp = cdir / "oci_api_key.pem"
kp.write_bytes(await private_key.read()); kp.chmod(0o600)
key_bytes = await private_key.read()
kp.write_bytes(key_bytes); kp.chmod(0o600)
# Detect encrypted keys that require passphrase
key_text = key_bytes.decode("utf-8", errors="ignore")
key_is_encrypted = "ENCRYPTED" in key_text or "Proc-Type: 4,ENCRYPTED" in key_text
if key_is_encrypted and not key_passphrase:
# Clean up and warn
shutil.rmtree(cdir, ignore_errors=True)
raise HTTPException(400, "A chave privada está criptografada (ENCRYPTED). Informe a Key Passphrase.")
if public_key: (cdir / "oci_api_key_public.pem").write_bytes(await public_key.read())
cfg_file = cdir / "config"
cfg_content = (f"[DEFAULT]\nuser={user_ocid}\nfingerprint={fingerprint}\n"
@@ -444,11 +452,14 @@ async def test_oci(cid: str, u=Depends(require("admin","user"))):
_config_log("oci", cid, cname, "error", "test", "Config não encontrada", u["id"], u["username"])
return {"status":"error","message":"Config não encontrada"}
try:
r = subprocess.run(["oci","iam","region","list","--config-file",str(cp),"--output","json"], capture_output=True, text=True, timeout=30)
r = subprocess.run(["oci","iam","region","list","--config-file",str(cp),"--output","json"],
capture_output=True, text=True, timeout=30, stdin=subprocess.DEVNULL)
if r.returncode == 0:
_config_log("oci", cid, cname, "success", "test", "Conexão OK", u["id"], u["username"])
return {"status":"success","message":"Conexão OK","data":json.loads(r.stdout)}
msg = r.stderr[:500]
if "passphrase" in msg.lower() or "getpass" in msg.lower():
msg = "A chave privada requer passphrase. Recadastre a credencial informando a Key Passphrase."
_config_log("oci", cid, cname, "error", "test", msg, u["id"], u["username"])
return {"status":"error","message":msg}
except FileNotFoundError: