Solución:
¿Cuál es el problema? file.close()
cerrará el archivo aunque esté abierto con os.open()
.
with os.fdopen(os.open('/path/to/file', os.O_WRONLY | os.O_CREAT, 0o600), 'w') as handle:
handle.write(...)
Esta respuesta aborda múltiples preocupaciones con la respuesta de vartec, especialmente el umask
preocupación.
import os
import stat
# Define file params
fname="/tmp/myfile"
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL # Refer to "man 2 open".
mode = stat.S_IRUSR | stat.S_IWUSR # This is 0o600.
umask = 0o777 ^ mode # Prevents always downgrading umask to 0.
# For security, remove file with potentially elevated mode
try:
os.remove(fname)
except OSError:
pass
# Open file descriptor
umask_original = os.umask(umask)
try:
fdesc = os.open(fname, flags, mode)
finally:
os.umask(umask_original)
# Open file handle and write to file
with os.fdopen(fdesc, 'w') as fout:
fout.write('somethingn')
Si el modo deseado es 0600
, se puede especificar más claramente como el número octal 0o600
. Aún mejor, solo usa el stat
módulo.
Aunque primero se elimine el archivo antiguo, aún es posible una condición de carrera. Incluso os.O_EXCL
con os.O_CREAT
en las banderas evitará que se cree el archivo si existe debido a una condición de carrera. Esta es una medida de seguridad secundaria necesaria para evitar abrir un archivo que ya puede existir con una mode
. En Python 3, FileExistsError
con [Errno 17] se genera si el archivo existe.
Si no se configura primero el umask
para 0
o para 0o777 ^ mode
puede dar lugar a una incorrecta mode
(permiso) establecido por os.open
. Esto se debe a que el umask
por lo general no es 0
, y se aplicará a la especificada mode
. Por ejemplo, si mi original umask
es 2
es decir 0o002
, y mi modo especificado es 0o222
, si no configuro primero el umask
, el archivo resultante puede tener un mode
de 0o220
, que no es lo que quería. Por man 2 open
, el modo del archivo creado es mode & ~umask
.
los umask
se restaura a su valor original lo antes posible. Esta obtención y configuración no es segura para subprocesos, y una threading.Lock
debe utilizarse en una aplicación multiproceso.
Para obtener más información sobre umask, consulte este hilo.
actualizar
Amigos, si bien les agradezco por los votos a favor aquí, yo mismo tengo que argumentar en contra de mi solución propuesta originalmente a continuación. La razón es hacer las cosas de esta manera, habrá una cantidad de tiempo, por pequeña que sea, en la que el archivo exista y no tenga los permisos adecuados en su lugar; esto deja abiertas amplias formas de ataque e incluso un comportamiento con errores.
Por supuesto, crear el archivo con los permisos correctos en primer lugar es el camino a seguir, en contra de la corrección de eso, utilizando Python with
es solo un caramelo.
Así que, por favor, tome esta respuesta como un ejemplo de “qué no hacer”;
publicación original
Puedes usar os.chmod
en lugar de:
>>> import os
>>> name = "eek.txt"
>>> with open(name, "wt") as myfile:
... os.chmod(name, 0o600)
... myfile.write("eeek")
...
>>> os.system("ls -lh " + name)
-rw------- 1 gwidion gwidion 4 2011-04-11 13:47 eek.txt
0
>>>
(Tenga en cuenta que la forma de usar octals en Python es siendo explícito, prefijándolo con “0o
” como en “0o600
“. En Python 2.x funcionaría escribiendo solo 0600
– pero eso es engañoso y desaprobado.)
Sin embargo, si su seguridad es crítica, probablemente debería recurrir a crearla con os.open
, como lo haces y usas os.fdopen
para recuperar un objeto de archivo Python del descriptor de archivo devuelto por os.open
.