Reputation: 1
I am implementing parental control app via python 3.9 for macOS. Therefore I want to use launch agent to keep my application always alive (app reopened automatically after reboot pc and protected against to be closed via activity monitor.) I want to give keep alive enabling and disabling option to parents that they can deactivate or activate it in the app GUI.
I achieved to keep alive my app standalone signed app without sandboxing(or via Terminal command) but if I sign it with sandbox then I get following error for "launchctl load" and "launchctl bootstrap" commands which are executed in the application "Load failed: 5: Input/output error"
My steps without Sandbox which works fine:
1- Create a com.test_gui.macos.plist file under /Library/LaunchAgents with following content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>test_gui</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>-g</string>
<string>-a</string>
<string>/Applications/test_gui.app</string>
</array>
</dict>
</plist>
2- create a python file for launch agent activation (I know either launchctl load or bootstrap should be used but I used both of them to test both.):
import subprocess
cmd = "launchctl enable gui/501/test_gui"
response = subprocess.call(cmd, shell=True)
time.sleep(2)
cmd = "launchctl load -w /Library/LaunchAgents/com.test_gui.macos.plist"
response = subprocess.call(cmd, shell=True)
time.sleep(2)
cmd = "launchctl bootstrap system /Library/LaunchAgents/com.test_gui.macos.plist"
response = subprocess.call(cmd, shell=True)
time.sleep(50)
3- Create standalone app via nutika:
python3.9 -m nuitka --run --standalone --macos-disable-console --macos-create-app-bundle
\--macos-app-mode=ui-element --enable-plugin=pyside6 --macos-app-icon=/Users/emre/Documents/MrProtect/icons/app_icon.png
\--include-data-dir=icons=icons test_gui.py
4-Create a .sh file to sign app without sandboxing:
#!/bin/sh
#
# Creates ./dist/HelloAppStore.app
#
APP_PATH="/Users/emre/Documents/tests/Deployment/test_gui.app"
SIGNING_IDENTITY_APP="Apple Development: Emre Guenay (xxx)"
PASSWORD="xxx"
codesign -s "$SIGNING_IDENTITY_APP" -f \
"$APP_PATH/Contents/MacOS/Python"
codesign -s "$SIGNING_IDENTITY_APP" -f \
"$APP_PATH/Contents/MacOS/test_gui"
exit 0
5-execute sh file and see following output: /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/Python: replacing existing signature /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/test_gui: replacing existing signature
6-copy paste signed standalone app(without sandbox) file under /Applications/
7-execute app and try to close app via activity monitor and observe that the app is reopened automatically. so the launch agent works fine
Failed Steps(Sign the same app with sandbox and observe that both launchctl load and bootstrap returns "Load failed: 5: Input/output error")
8- create an app.entitlements file with following content:
\<?xml version="1.0" encoding="UTF-8"?\>
\<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"\>
\<plist version="1.0"\>
\<dict\>
\<key\>com.apple.security.app-sandbox\</key\>
\<true/\>
\</dict\>
\</plist\>
9-Create a .sh file to sign app with sandboxing:
#!/bin/sh
#
# Creates ./dist/HelloAppStore.app
#
APP_PATH="/Users/emre/Documents/tests/Deployment/test_gui.app"
SIGNING_IDENTITY_APP="Apple Development: Emre Guenay (xxx)"
PASSWORD="xxx"
codesign -s "$SIGNING_IDENTITY_APP" -f \
\--entitlements app.entitlements \
"$APP_PATH/Contents/MacOS/Python"
codesign -s "$SIGNING_IDENTITY_APP" -f \
\--entitlements app.entitlements \
"$APP_PATH/Contents/MacOS/test_gui"
exit 0
10-execute sh file and see following output: /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/Python: replacing existing signature /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/test_gui: replacing existing signature
11-execute app and try to close app via activity monitor and observe that the app is closed although app started the launch agent.
12-you can re-execute app under /Applications/test_gui.app/Contents/MacOS folder with "./test_gui" or even with sudo "sudo ./test_gui" commands you would see following error message for both launchctl load and bootstrap returns: "Load failed: 5: Input/output error". So if you close the app, it will not be re-opened
My 2 questions:
1-Is there any other method different than launch agent for keep alive? I researched it in internet but I could not find any other method unfortunately. Moreover launch agent is not user friendly anyway, with the reason that sandboxed apps cannot copy paste any files under LaunchAgents folder automatically. I am planning to provide my plist file to users that they can copy paste the file themself into launch agent folder out of sandbox.
2-How can i get rid of "Load failed: 5: Input/output error", thereby I can proceed at least with lanuchctl?
What I have tried additionally:
1-I have also tried to use these linux commands, before executing my sandboxed standalone app file:
sudo -S chown 600 /Library/LaunchAgents/com.test_gui.macos.plist
sudo -S chown root:wheel /Library/LaunchAgents/com.test_gui.macos.plist
2-I have already given security fulldisk access to my test_gui app, but it also did not work
My Requirements:
Nuitka:
1.9rc5
Commercial: None
Python: 3.9.12 (v3.9.12:b28265d7e6, Mar 23 2022, 18:22:40)
Flavor: CPython Official
Executable: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9
OS: Darwin
Arch: x86_64
Version C compiler: /usr/bin/clang (clang).
macOS Sonoma: 14.2.1
Upvotes: 0
Views: 1214