1

This problem involves the collision of several problems, all of which I understand only somewhat well, but I include them together because they could all be the entry point for a solution. Here is the best description I can give.

I have an app, in python. (I imagine I could theoretically solve all of these problems by learning Cocoa and ObjectiveC, but that seems like QUITE a lift, for this problem -- AND, as noted below, this problem may not actually be related to python, really, at all. I just don't know.) A CORE feature of this app is to trigger a minigame, with a hotkey -- meaning, the hotkey itself is fundamental to the desired functionality. And furthermore, I would really like to package this app, to let other people use it. (Locally, it works great! Hey!)

The problem starts with the fact that adding the hotkey -- which I am doing with

import keyboard
keyboard.add_hotkey('windows+shift+y', trigger_minigame)

-- requires root access. Due to DIRE WARNINGS in another SO post Forcing a GUI application to run as root (which, honestly, I only vaguely understand), I would like to grant that access to ONLY this part of the program. I IMAGINE, such an approach would look something like this:

# needs_root.py
import keyboard
from shouldnt_have_root import trigger_minigame
keyboard.add_hotkey('windows+shift+y', trigger_minigame)

# shouldnt_have_root.py
def minigame():
    buncha pygame, GUI stuff (which is dangerous???)
def trigger_minigame():
    adds event to minigame's event queue

# bash script
sudo python needs_root.py

HOWEVER -- there are several major challenges! The biggest is that I don't even know if THAT is safe, since I don't know how security and permissions (especially with imports) works at all! And more generally, how dangerous are the imports? It appears that I may in fact have to import substantially more, to make it clear what event queue the trigger is adding an event TO -- and I don't know how to have that communication happen, while still isolating the GUI parts (or generally dangerous ones) from unnecessary and hazardous access.

There's another layer too though; packaging it through pyinstaller means that I can't target the scripts directly, because they'll have been turned into binaries, but according to THIS answer Packaging multiple scripts in PyInstaller it appears I can just target the binaries instead, i.e. have the first binary call

osascript -e 'do shell script "python needs_root_binary" with admin.'

to get the user to bless only the necessary part, but I don't know if that will put OTHER obstacles, or vulnerabilities (or inter-file communication difficulties), in the way.

LAST, I could try STARTING as root, and then switching away from it, as soon as the hotkey is set (and before anything else happens) -- but would that be safe? I'm still worried about the fact that it involves running sudo on the whole app.

In any event --

is this as big a mess as it feels?

How do I give root access to only a piece of a packaged .app, that I've written in python?

one_observation
  • 454
  • 5
  • 16

2 Answers2

1

I'd advice You to:

  1. enable the root access,
  2. write the script,
  3. disable the root access

as it's closer described in here.

The Pyinstaller is another chapter. When I was making software requiring usage of hotkeys, I was forced to use another than keyboard, because it wasn't working properly on PC without Python, therefore I made a hotkey with tkinter built-in function canvas.bind() (more info here).

Hopefully I helped.

TheOne
  • 330
  • 7
  • 25
  • Extremely interesting, thank you -- does the tkinter solution work even when its window is not in focus? 'keyboard' has the nice property of being global, so the process can run in the background, and the hotkey pulls up the game to be played. About the permissions though, I'll try this solution and get back to you. – one_observation Aug 21 '18 at 03:15
  • Not by default, but you can assign focus to it (https://stackoverflow.com/questions/15269682/python-tkinter-canvas-fail-to-bind-keyboard),see B. Oakley's answer – TheOne Aug 21 '18 at 06:44
  • I'm so sorry! I literally clicked on the wrong answer -- that bounty was meant for you. Honest apologies. – one_observation Aug 27 '18 at 00:00
-1

You can not run a specific Python function as root, only the Python process executing your script can be run with elevated permissions.

So my answer is: your problem as described is unsolvable.

rocksportrocker
  • 7,251
  • 2
  • 31
  • 48
  • I don't believe that correctly characterizes what I'm trying to do, but more immediately, does that mean the solution of changing permission levels, as described in the other answer, is not a meaningful one? I've seen many people use `os.seteuid()` to take root away from a process. – one_observation Aug 25 '18 at 19:25
  • You can not change the user / userid executing your program within the script. The user must execute `sudo` on the start of the Python interpreter. In case setting the hot key persists after your program ends, you also could write two programs and ask the user to run the hotkey modification once as root after installation. – rocksportrocker Aug 26 '18 at 08:46
  • But then, if you start with root, then use `os.setueid` to some id that's not root, what does that accomplish? As I understand, the point of the function is to change the userid. – one_observation Aug 26 '18 at 13:03
  • Actually -- that bounty was a mistake. I'm sorry, I didn't find this helpful at all. – one_observation Aug 27 '18 at 00:00
  • `setuid` is also bound on permissions and rules. There can be users on a system which are allowed to use `setuid` and others which are disallowed. Try a two line Python script importing `os` and then calling `os.setuid(0)` and see what happens. Standard users are not allowed, and those who are, are quite close to `root` in their role. – rocksportrocker Aug 27 '18 at 08:53
  • The other solution you linked to in your question uses Python to start a separate process as root. So you just automate doing `sudo`, which be achieved using a shell script. An arbitrary process running under a common user account can not elevate its privileges. – rocksportrocker Aug 29 '18 at 14:37