I recently created a new user. I want to allow this user to use only one or two programs, but I have lots of systemwide installed apps. Is there an easy way to exclude a specific user from using apps (without reinstalling everything again)?
3 Answers
Below a combination of measures you can take, to restrict users locally from using defined applications. They are not meant (nor fit) for unattended usage, in public spaces for example, but do create a usable restricted desktop. It is mainly the combination of measures that makes it more difficult to bypass. Furthermore if someone manages to launch a "forbidden" application, it will be logged.
The answer is a bit extensive. The setup is not, and you are assisted by two scripts.
What the setup exists of
- A selection of software, made unavailable from the interface by editing their local desktop file by a script (further below)
- Making the terminal only available via password, so running applications from the terminal is made more difficult.
- Changing the default keycombination of opening the terminal, instead of ctrlaltt
- Logging the usage of a "blacklist" of software you define, in case some smart user might surpass your setup
How to setup
Setting up a broad selection of software, unavailable from the interface.
- Log in, to the user account you want to restrict
- Make a (temporary) folder (no matter where, on the desktop for example) to edit some files.
- Browse into the directory
/usr/share/applications
Select all (desktop files of) applications you want the user to be excluded from (don't select all of them without looking, some of them are necessary to set up your desktop) - Copy these desktop files into the temporary directory you created, for bulk-editing.
- Copy the text below, paste it into an empty file, save it in the same temporary folder as
no_openapp.py
. - CD into the directory(!) and run it with the command:
python3 no_openapp.py
.
The script did a few things:
1] Create a blacklist of commands (for later use, see further below) 2] Edit the desktop files to show a message instead of running the application. If you move the desktop files to ~/.local/share/applications
, on next login the applications will not run from Unity or Dash.
#!/usr/bin/python3
import os
import getpass
import subprocess
desktopfile_dir = os.getcwd()
file_list = os.listdir(os.getcwd())
edit_subjects = [desktopfile_dir+"/"+item for item in file_list]
def create_blacklist():
command_list = []
for item in edit_subjects:
with open(item) as blacklist_source:
searchlines = blacklist_source.readlines()
try:
native_command = [
line for line in searchlines if line.startswith("Exec=")
][0].replace("Exec=", "").replace("\n", "")
cleaned_command = native_command.split(" ")[0]
command_list.append(cleaned_command)
except IndexError:
pass
with open(desktopfile_dir+"/blacklist.txt", "wt") as created_blacklist:
created_blacklist.write(str(command_list))
def make_unavailable():
for item in edit_subjects:
try:
with open(item, "r") as make_unav:
lines = make_unav.readlines()
line_range = range(0, len(lines))
for index in line_range:
if lines[index].startswith("Exec="):
lines[index] = 'Exec=zenity --info --text="You are not allowed to use this application"\n'
else:
pass
with open(item, "wt") as make_unav:
for line in lines:
make_unav.write(line)
except (IsADirectoryError, IndexError, PermissionError):
pass
create_blacklist()
make_unavailable()
Restrict the use of the terminal
- make the terminal accesible with a password, like in this post.
if the user is familiar with the key combination of ctrlaltt, change the default combination:
System>Preferences>Keyboard Shortcuts > key combinations (tab).
In case you have a wizzkid bypass your measures, catch him
- In case a user manages to get a forbidden application running, make sure you catch him. for this, we use the blacklist, created in step one.
- create a folder on a hidden location. Copy the "blacklist.txt", created in step one to the directory.
- copy the text below, paste it into an empty textfile and save it to the same directory as the blacklist, as
processes.py
. open a terminal window, type
crontab -e
. add the following line to the crontab file:* * * * * cd /path/to/script; python3 processes.py
The blacklist is a list of process names. The script checks every minute if one of the black-listed applications is running, and keeps record in a log file (in the same directory as where the script is located). The name of the log file is log.txt. Optionally, you can make the script kill the forbidden application (not the default). To make it kill the application(s), change the line kill_apps = "no"
into kill_apps = "yes"
(in the head section of the sript).
#!/usr/bin/python3
import os
import datetime
import subprocess
import getpass
curr_dir = os.getcwd()
curruser = getpass.getuser()
# should forbidden applications be killed?
kill_apps = "yes"
def produce_commands_ofapp():
with open(curr_dir+"/blacklist.txt", "r") as blacklist:
blacklist = eval(blacklist.read())
return blacklist
def createlist_runningprocs():
processesb = subprocess.Popen(["ps", "-u", curruser], stdout=subprocess.PIPE)
process_listb = (processesb.communicate()[0].decode("utf-8")).split("\n")
return process_listb
def runsornot():
check_blacklist = produce_commands_ofapp()
runningprocs_list = createlist_runningprocs()
found_matches = [item for item in check_blacklist
if item[:15] in str(runningprocs_list)]
if len(found_matches) != 0:
with open(curr_dir+"/log.txt", "a+") as logfile:
logfile.write(str(found_matches)+" "+str(datetime.datetime.now())+"\n")
else:
pass
if kill_apps == "yes":
for application in found_matches:
kill_forbidden(application)
else:
pass
def kill_forbidden(app_command):
# get the pid length of system
get_size = subprocess.Popen(
["cat", "/proc/sys/kernel/pid_max"],
stdout=subprocess.PIPE
)
size = len((get_size.communicate()[0].decode("utf-8")).replace("\n", ""))
# get the appropriate pid line & pid
process_list = createlist_runningprocs()
appr_pid = [
line for line in process_list if \
app_command[:15] in line][0][:size+1].replace(" ", "")
# kill the found process
subprocess.Popen(["kill", "-9", appr_pid])
runsornot()
As said, the setup can be bypassed. However, the combination of measures, and the fact that you have to know what they are, make it a reasonable defence in case of an avarage usere with an average knowledge on how to manipulate the system.
-
Excellent post Jacob! I might have 1 addition: the crontab script could also be used to KILL the offending process. Or maybe a bit more difficult: gracefully exit it– RinzwindApr 23, 2014 at 17:40
-
@Rinzwind perfect! why didn't I think of that, will add it later, thanks!!! Apr 23, 2014 at 17:41
Thanks for your answers. I have reached this already by manipulating the permissions of the programs bin-files. I installed the old gnome user-administration tool, which allows to manage groups. Unchecked group games for the user, which is not allowed to open certain programs. Then changed group and permissions of the bin-files:
sudo chgrp games /path/to/game
sudo chmod 750 /path/to/game
Now the user can see the desktop files in the Dash, but they won't run after click.
Greetings
This is very, very difficult. I've never seen any setup that comes close to doing that and most times, when people want this, I've been able to provide much better solutions because there wasn't really any point in restricting the user to begin with – they just didn't know what other options Ubuntu has.
However, you might be able to do this by running the entire user session in an lxc container running Xspice, that simply don't have any other applications installed. It will be quite a project, but if and when it works, it should probably be the best isolation you could get. This idea is based on a blog post by Serge Hallyn recently found on Planet Ubuntu and you'll certainly want to read it: http://s3hh.wordpress.com/2014/04/18/xspice-in-containers/
It's complicated, based on new technologies that aren't even released yet, I don't know anyone who's actually tried it for these kinds of purposes – but in theory, it should work. :)
I would certainly recommend that you investigate other ways of accomplishing your true goal, which most likely isn't actually preventing the use of apps, but something else.