Start/Assign macOS app with root privileges - xcode

I have written a macOS Cocoa app using XCode 9.2.
The purpose of the app is as a wrapper to a set of shell commands so that users can run commands easily as required. The shell script allow the users to control a particular device driver for which the software is written by another party.
I have managed to get the app to invoke the shell command as root.
But there are some sub-commands that fail. The actual commands run are, and I think it is the 2nd "stop -a" that fails:
do shell script \"
cd '/Library/Application Support/ABC' ;
python '/Library/Application Support/ABC/abc.py' stop -d;
python '/Library/Application Support/ABC/abc.py' stop -a;
python '/Library/Application Support/ABC/abc.py' stop -g;
python '/Library/Application Support/ABC/abc.py' stop -t;\"
with administrator privileges
When I run the same commands in Terminal they work, either as discrete commands or in a shell script.
As a last resort I ran the app from the command line using
sudo ~/Library/Developer/Xcode/DerivedData/appname/Build/Products/Debug/appname.app/Contents/MacOS/appname
And this works perfectly.
So, it seems that when I run using the NSAppleScript framework, which correctly prompts me for the root password, there is still something amiss which causes the command failure. But when the whole app runs under sudo everything works.
So the solution appears to be to set the app to require Root privs. Is there a setting that can be set for the built project that would automatically set this such that the root password is requested on startup?

Seems to be working in that I do not get the error, but would still like some pointers on how to set an app to run as admin.

Related

How to launch a new process in a new terminal in Linux

I'm using Linux Mint 19 Cinnamon. I've an Angular project and I want to do the following things. All these in a separate terminal:
Navigate into project folder and run code . so that I can see the code on Visual studio.
Navigate into project folder and run ng serve to launch my application and keep it running.
Navigate into project folder and run node server.js to start backend server and keep it running.
this is very painful as the project location is-
home/xpert/Documents/social-coder
and it contains two servers:
social-coder/application The angular server that runs on localhost:4200
social-coder/server/server.js The backend server that runs on localhost:3000
Both the servers need to be constantly running for the application to work.
Navigating again and again with a new terminal is what wasting my time. I decided to write a shell script so that I can do all at once with one single click. This is what my .bashrc file contains:
alias first='gnome-terminal | npm start --prefix Documents/social-coder/application'
alias second='node Documents/social-coder/server/server.js'
alias third='code Documents/social-coder'
This is what I've thought. SO, all of the above 3 commands works perfectly If I manually copy-paste them in separate terminals. But again, I have to manually open 3 different terminals and make them run. I'm coming from:
How to write practical shell scripts - Like Geeks
Run command on another(new) terminal window
How to Use GNOME Terminal App
gnome-terminal opens a new terminal but still runs npm start from the same terminal itself.
I admit that I'm a newbie and there are gaps in my knowledge. Please correct me.
For now I've created a command using pipe. It is working but I'm not sure whether this is the preferred way or not:
gnome-terminal -- /bin/bash -c 'npm start --prefix Documents/social-coder/application' | gnome-terminal -- /bin/bash -c 'node Documents/social-coder/server/server.js' | gnome-terminal -- /bin/bash -c 'code Documents/social-coder'
Please feel free to edit this answer.

When my pkg runs its Post-installation script, how can I know how that happened?

There are two ways this script can be run: When the user opens the pkg file and goes through the normal GUI setup, or when an admin (or savvy user) runs sudo installer -pkg /path/to/Installer.pkg -target /. For the second one, I want to know when the script was run in this mode so I can make more admin-friendly decisions like not opening another GUI. How do I know when my pkg is installed via the command line?
I'm hoping for some environment variable or something similar.
Running the script via sudo will change the values of certain variables and add others in. Your script could check for the existence of those variables (or their values) to make a determination as to whether the installer was run via sudo.
Values that would get updated:
HOME
LOGNAME
MAIL
Values that would get set:
SUDO_COMMAND -- the command that was run via sudo
SUDO_GID -- the GID of the user that ran sudo
SUDO_UID -- the UID of the user that ran sudo
SUDO_USER -- the username of the user that ran sudo
My recommendation would be to check for the existence of the SUDO_COMMAND environment variable; it is unlikely to be set for a non-sudo installation, and would be set for a sudo-based installation.
Reference: sudo 1.8.20 manual - ENVIRONMENT section
Since this was being run by the installer command, the COMMAND_LINE_INSTALL environment variable is set to 1. When opening the pkg normally, this variable is not set at all.
So:
if [ $COMMAND_LINE_INSTALL ]; then
# Do stuff for CLI land
else
# Do stuff for GUI land
fi

How do I run a shell script with administrator privileges through AppleScript without prompting for a password?

I want to have my AppleScript application run a Python script with sudo, but I don't want the application to prompt the user for a password (our users do not have sudo privileges).
The Python script has been added to the /etc/sudoers file appropriately (ALL ALL=NOPASSWD: /path/to/script.py). In the terminal, I can do (as a regular, non-privileged user):
$ sudo ./script.py
and it runs perfectly well. But in AppleScript when you try to do:
do shell script "sudo ./script.py"
You of course get the "sudo: no tty present and no askpass program specified" error. But if you change it to:
do shell script "./script.py" with administrator privileges
AppleScript insists on presenting a popup window to ask for the password. I have also tried passing a null password to sudo with a pipe:
do shell script "echo '' | sudo -S ./script.py"
but that also does not work. (I think it tries to run sudo individually first and then pass the command through, which won't work because the user doesn't have sudo privileges!)
I need a solution where AppleScript will run the Python script with sudo. I would prefer the script stays unreadable and un-executable by average users for security reasons, and is only executed through the AppleScript. (I know that, hypothetically, the users could call sudo script.py and it would run, but that's assuming they even know about sudoers; I'm trying to keep it as secure as possible while still usable).
I'm still pretty new to AppleScript, so any help would be greatly appreciated! Thanks!
When I added ALL ALL=NOPASSWD: /Users/myusername/a to sudoers and ran echo $'#!/bin/bash\nsay $(ls ~root|head -n1)'>~/a;chmod +x ~/a, do shell script "sudo ~/a" ran the script as root without requiring a password.
I'm guessing the problem is that you specified the path like do shell script "sudo ./script.py". Try to use do shell script "sudo ~/script.py" instead. The default working directory is for do shell script is / and not ~/.

How to use sudo inside of a Run Script build phase in Xcode 4?

I need use execute a command inside of a script in a Run Script build phase in Xcode 4 using sudo. However, the compiler complains:
sudo: no tty present and no askpass program specified
Anyone have a clever solution for this problem?
One solution is to place the sudo password in an executable shell script like the following:
#!/bin/bash
echo thesudopassword
This shell script might be called password.sh
Then, setup the environment variable SUDO_ASKPASS=password.sh
Once this is setup, the -A option can be passed to sudo. This option uses the ASKPASS program to obtain the sudo password. The ASKPASS program need only write the password to stdout.
So, for example,
sudo -A ditto -V /tmp/testserver.dst /
This is obviously a rather insecure solution, but it does work.
Two ideas that haven't been suggested yet, both of which are probably better/safer than the currently accepted answer:
First option would be to put the part of the script that needs to be run as root in a script file (.sh or something), and then make it setuid as root: chmod go-w,+sx scriptfile, sudo chown root scriptfile. This means that script will automatically run as root, which avoids you needing to authenticate to run it (just to change it). As long as its operation isn't subject to user input, this should be quite safe. (Of course, if you make a script that takes an input argument and deletes it or runs it, or does most anything else with it, that would not be safe.)
Second option would be to use applescript (possibly via osascript). Applescript allows you to do shell script "sudo command goes here" with administrator privileges, which will pop up a graphical dialog asking for a password.
The first of these options would be good for an automated environment, though it might not deal well with (for example) being checked into an SCM, or being sent to another user. The second option would work better with that, but requires a password input every time, so doesn't work as well for an automated build script.
Another solution to this problem is to modify sudoers file and add your account to it and state that you should never be asked for the sudo password. To accomplish this is fairly straightforward:
run:
sudo visudo
In the User privilege specification section add a line that looks like
youraccountname ALL=(ALL) NOPASSWD: ALL
Of course, this can be a dangerous thing to do, so be careful. I would suggest reading the man page for sudoers and visudo before going this route.
After much searching I found the following solution.
https://forum.juce.com/t/build-script-for-automatically-moving-built-aus-into-components-folder-xcode/13112
Summary
Create a keychain and store your admin password in the keychain
Create a script which uses /usr/bin/security to access the password In your run script,
Set the ASK_PASS env variable and use the -A option with sudo
You can either run commands directly as a administrator with the following (changing echo YourCommandHere > /tmp/hello to your command):
osascript -e 'do shell script "sudo echo YourCommandHere > /tmp/hello " with administrator privileges'
Or run a script in your source directory using:
osascript -e 'do shell script "bash -x $SOURCE_ROOT/MyAdminScript.sh 1>/tmp/build-log 2>/tmp/build-log.err" with administrator privileges'
This runs the script and logs it output to /tmp/build-log and /tmp/build-log.err
For useful variables in the script see https://help.apple.com/xcode/mac/8.0/#/itcaec37c2a6
You can also execute XCode giving it the project as parameter from the Terminal using sudo like this:
sudo /Developer/Applications/Xcode.app/Contents/MacOS/Xcode /path/to/your/project.xcodeproj
This is the easiest solution I could think of, but there may be some drawbacks, since you would be executing XCode as root.
No need to write your sudo password anywhere. Just open a terminal window and type
$ sudo echo "hello"
Once you've typed your password, it will be good for a while - not sure how long - and the shell spawned by Xcode will inherit this permission.
If you get the "no tty present" message again later, just repeat the procedure

Capistrano :shell example

I'm currently using Capistrano to deploy my web application which works like a charm.
In my new project I must execute a command from sudo /bin/bash shell.
Is it possible for Capistrano to login to the machine as user X, run sudo /bin/bash,
enter the password and then execute a command in the sudo shell? If yes, could you
please provived me with an example.
With regards
jakob
Is there a specific reason you need to be in a root shell rather than executing the command with sudo? If executing a command with sudo, you can simply sudo 'command' instead of run 'command'.
I did a little experimentation to try to get a root shell with capistrano without logging into the server directly as root, and wasn't able to make much progress.
If running with sudo won't work, please update your question to let us know why and maybe we can help you find a workaround for it.
Update:
After playing around a little more, I found that you can execute an individual command (or string of commands) in a root shell by doing something like sudo '/bin/bash -c "whoami"'. It's getting an interactive root shell that's tricky.

Resources