htpasswd: reescritura en sitio cuando /etc/nginx no es escribible (alta de usuarios y cambio de contraseña)
This commit is contained in:
parent
62a31c05d7
commit
84a171ca73
@ -495,18 +495,33 @@ def _leer_htpasswd():
|
|||||||
|
|
||||||
|
|
||||||
def _escribir_htpasswd(lineas):
|
def _escribir_htpasswd(lineas):
|
||||||
"""Reescribe el archivo de forma atómica, conservando permisos y dueño."""
|
"""Reescribe el archivo de usuarios.
|
||||||
|
|
||||||
|
Si la carpeta es escribible (p. ej. en pruebas) se hace de forma atómica (temporal + rename)
|
||||||
|
conservando permisos y dueño. En producción el archivo vive en /etc/nginx, que es de root y
|
||||||
|
NO es escribible por el servicio aunque el archivo sí lo sea (chown leo:www-data + 640):
|
||||||
|
entonces se reescribe EN SITIO (r+ / truncate), que solo requiere permiso sobre el archivo.
|
||||||
|
Las rutas que llaman a esta función toman antes el candado HTPASSWD_LOCK."""
|
||||||
|
contenido = "\n".join(l for l in lineas if l is not None) + "\n"
|
||||||
carpeta = os.path.dirname(HTPASSWD) or "."
|
carpeta = os.path.dirname(HTPASSWD) or "."
|
||||||
st = os.stat(HTPASSWD)
|
st = os.stat(HTPASSWD)
|
||||||
tmp = os.path.join(carpeta, ".htpasswd.tmp-" + uuid.uuid4().hex[:8])
|
if os.access(carpeta, os.W_OK):
|
||||||
with open(tmp, "w", encoding="utf-8") as f:
|
tmp = os.path.join(carpeta, ".htpasswd.tmp-" + uuid.uuid4().hex[:8])
|
||||||
f.write("\n".join(lineas) + "\n")
|
with open(tmp, "w", encoding="utf-8") as f:
|
||||||
os.chmod(tmp, st.st_mode & 0o7777)
|
f.write(contenido)
|
||||||
try:
|
os.chmod(tmp, st.st_mode & 0o7777)
|
||||||
os.chown(tmp, st.st_uid, st.st_gid)
|
try:
|
||||||
except PermissionError:
|
os.chown(tmp, st.st_uid, st.st_gid)
|
||||||
pass
|
except PermissionError:
|
||||||
os.replace(tmp, HTPASSWD)
|
pass
|
||||||
|
os.replace(tmp, HTPASSWD)
|
||||||
|
return
|
||||||
|
with open(HTPASSWD, "r+", encoding="utf-8") as f: # PermissionError aquí = archivo no escribible
|
||||||
|
f.seek(0)
|
||||||
|
f.write(contenido)
|
||||||
|
f.truncate()
|
||||||
|
f.flush()
|
||||||
|
os.fsync(f.fileno())
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/usuarios")
|
@app.get("/api/usuarios")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user