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:
@@ -399,7 +399,15 @@ async def save_oci(
|
|||||||
):
|
):
|
||||||
cid = str(uuid.uuid4()); cdir = OCI_DIR / cid; cdir.mkdir(parents=True)
|
cid = str(uuid.uuid4()); cdir = OCI_DIR / cid; cdir.mkdir(parents=True)
|
||||||
kp = cdir / "oci_api_key.pem"
|
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())
|
if public_key: (cdir / "oci_api_key_public.pem").write_bytes(await public_key.read())
|
||||||
cfg_file = cdir / "config"
|
cfg_file = cdir / "config"
|
||||||
cfg_content = (f"[DEFAULT]\nuser={user_ocid}\nfingerprint={fingerprint}\n"
|
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"])
|
_config_log("oci", cid, cname, "error", "test", "Config não encontrada", u["id"], u["username"])
|
||||||
return {"status":"error","message":"Config não encontrada"}
|
return {"status":"error","message":"Config não encontrada"}
|
||||||
try:
|
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:
|
if r.returncode == 0:
|
||||||
_config_log("oci", cid, cname, "success", "test", "Conexão OK", u["id"], u["username"])
|
_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)}
|
return {"status":"success","message":"Conexão OK","data":json.loads(r.stdout)}
|
||||||
msg = r.stderr[:500]
|
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"])
|
_config_log("oci", cid, cname, "error", "test", msg, u["id"], u["username"])
|
||||||
return {"status":"error","message":msg}
|
return {"status":"error","message":msg}
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
|||||||
Reference in New Issue
Block a user