Después de actualizar a Mojave, mi script de copia de seguridad basado en rsync ejecutado a través de un agente de inicio en ~ / Library / LaunchAgents, ya no podía leer algunos directorios en ~ / Library.
Después de actualizar a Mojave, mi script de copia de seguridad basado en rsync ejecutado a través de un agente de inicio en ~ / Library / LaunchAgents, ya no podía leer algunos directorios en ~ / Library.
He pasado algunas semanas tratando de resolver esto. Estoy de acuerdo en que la respuesta actualmente aceptada no es realmente una solución, no es mucho mejor que simplemente deshabilitar el SIP por completo.
Mi solución es una solución totalmente intrincada, pero no requiere la inclusión de bash
en la lista blanca por completo. Actualización: Una solución un poco menos complicada a continuación.
open /path/to/MyApp.app
, pero no utilizando directamente el ejecutable almacenado en, por ejemplo, MyApp.app/Contents/Resources/
) Para el Paso 1, puede empaquetar fácilmente su script como una aplicación utilizando herramientas integradas en MacOS como Automator.app o Script Editor, o Platypus también funciona.
El contenido de ejemplo de una aplicación de este tipo podría ser un AppleScript simple (en el Editor de secuencias de comandos) como:
on run
do shell script "/usr/local/bin/bash /path/to/myscript.sh"
end run
Desde el Editor de secuencias de comandos, use el menú desplegable en el menú de guardar para guardar como una aplicación, luego CERRAR EDITOR DE ESCRITURA .
Agregue esta aplicación a Full Disk Access a través de System Preferences
- > Security & Privacy
.
NB: Si no guardó y cerró el Editor de secuencias de comandos antes de agregarlo a la FDA como se le indicó, parece que algún tipo de proceso invisible (¿salvado de fondo automatizado?) cambiará algo (algún tipo de la marca de tiempo o hash?) que se requiere para el acceso completo al disco, que puede resolver algunos errores intermitentes que fueron un gran dolor de cabeza. Entonces, si no hizo esto, elimine su aplicación de la FDA, guarde y cierre el Editor de secuencias de comandos, luego agregue de nuevo a la FDA.
Para su LaunchAgent, use algo como:
<string>/usr/bin/open</string>
<string>/path/to/MyApp.app</string>
Si su script de copia de seguridad necesita acceso a la raíz (por ejemplo, para realizar una copia de seguridad de los archivos 0600 de propiedad de la raíz), se encontrará con otro conjunto de soluciones piratas, ya que /usr/bin/open
no ejecutará nada como raíz (incluso si especifique la clave UserName
en una propiedad raíz de /Library/LaunchDaemons/
plist. (Me complacería abrir esta como una pregunta separada si corresponde, ya que creo que la solución a continuación deja mucho que desear).
Una opción para esto es agregar with administrator privileges
en su AppleScript, pero esto requiere ingresar manualmente su contraseña, anulando el propósito de la copia de seguridad automática. Mi solución actual es:
sudo visudo
y le doy a mi usuario sin privilegios la capacidad de ejecutar mi script de copia de seguridad como sudo con NOPASSWD: (También especifico el hash del script para mejorar la seguridad, por ejemplo, myuser ALL=(ALL) NOPASSWD: sha256:hashgoeshere /path/to/myscript.sh
) sudo chown root myscript.sh
sudo chmod 0740 myscript.sh
(4 por lo que aún se puede agregar a VCS) do shell script "sudo -n /path/to/myscript.sh"
y vuelva a guardarlo como MyApp.app Lecturas / detalles adicionales:
Después de algunas pruebas preliminares, parece que una solución un poco menos compleja es compilar un binario (que usa un lenguaje compilado) que llama a su script de bash. Agregue ese binario a la FDA y parece funcionar. Agrega a /Library/LaunchDaemons
plist, que es propiedad de la raíz, y tienes una manera de llamarlo desde root
sin toda la locura que se muestra arriba.
Ejemplo de script en Go:
// Runrestic provides a binary to run my restic backup script in MacOS Mojave with Full Disk Access
package main
import (
"log"
"os"
"os/exec"
"path/filepath"
)
func main() {
ex, err := os.Executable()
if err != nil {
log.Fatal(err)
}
dir := filepath.Dir(ex)
script := filepath.Join(dir, "restic-backup.sh")
cmd := exec.Command("/usr/local/bin/bash", script)
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
Para seguridad, yo sudo chown root
y sudo chmod 0700
el binario resultante antes de agregar a Full Disk Access
(aunque es cierto que un atacante podría simplemente cambiar el script de bash que esto llama si se dejara sin protección).
Resolví esto de la siguiente manera:
El error que cometí fue que el agente de inicio ejecutó el script de esta forma:
<key>ProgramArguments</key>
<array>
<string>/Users/channing/bin/backup.sh</string>
</array>
Haz esto en su lugar
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/channing/bin/backup.sh</string>
</array>
Reinicia tu agente:
launchctl unload ~/Library/LaunchAgents/backup.plist
launchctl load ~/Library/LaunchAgents/backup.plist
Alégrate.
Hice algunas pruebas más y parece que ya no puedo dar acceso completo al disco a ningún normal †. Escribí un script de shell mínimo [1], un binario mínimo que llama a ese script de shell [2] y un binario que intenta acceder a una ubicación segura [3]. Luego di todos estos scripts / ejecutables Full Disk Access , y también a /bin/sh
por si acaso.
Llamar a cualquiera de estos directamente a través del shell me da un error.
Luego me topé con una discusión en los foros de desarrolladores de Apple sobre Reglas para el acceso completo al disco . Parece que necesita un paquete de aplicaciones para otorgar los permisos de Acceso total al disco , lo que explica por qué otorgar acceso completo al disco a una aplicación de terminal permite que esa aplicación llame al ls ~/Library/Mail
con éxito.
Sin embargo, no explica por qué puede otorgar acceso a /bin/bash
y luego usarlo en su archivo launchd.plist
para tener acceso completo al disco en su script de shell.
† binario simple, no un App Bundle que vive en /Applications
[1] /Users/me/access-test.sh
:
#!/bin/sh
ls /Users/me/Library/Mail
[2] /Users/me/access-test.c
:
#include <unistd.h>
int main(int argc, char *const argv[]) {
const char *file = "/Users/me/access-test.sh";
return execvp(file, argv);
}
[3] /Users/me/access-test-2.c
:
#include <stdio.h>
#include <dirent.h>
int main(void) {
DIR *dp;
struct dirent *ep;
dp = opendir("/Users/me/Library/Mail");
if (dp == NULL) {
perror("Couldn't open directory");
return 1;
} else {
while ((ep = readdir(dp))) {
puts(ep->d_name);
}
closedir (dp);
}
}
Vaya a Preferencias del sistema → Seguridad & Privacidad → Privacidad → Acceso total al disco . Luego haga clic en el candado para realizar cambios, haga clic en el botón + y agregue su script.
La próxima vez que launchd
inicie su script, tendrá acceso total al disco y pasará estos permisos a cualquier subproceso que genere, como rsync
en su caso.
Esto funciona para cualquier ejecutable que desee iniciar utilizando un agente de inicio. Solo agregue el ejecutable (dado como valor para <key>Program</key>
o el primer valor de <key>ProgramArguments</key>
en su archivo plist ) a la lista de programas que tienen acceso total al disco .
Tengo el mismo problema con algunas copias que activé a través de launchd que usan ídem. También estoy probando algunas pruebas para ver qué puedo agregar mínimamente en Full Disk Access para que funcione. Para los scripts de bash, me pregunto si es posible que pueda crear una aplicación AppleScript y usarla para otorgar el acceso y llamar al script. Puede darle una manera de otorgar acceso a esa aplicación específica y evitar el acceso a todas las cosas que podría ejecutar a través de bash