1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
1 |
# IVLE - Informatics Virtual Learning Environment
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
2 |
# Copyright (C) 2007-2009 The University of Melbourne
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
3 |
#
|
4 |
# This program is free software; you can redistribute it and/or modify
|
|
5 |
# it under the terms of the GNU General Public License as published by
|
|
6 |
# the Free Software Foundation; either version 2 of the License, or
|
|
7 |
# (at your option) any later version.
|
|
8 |
#
|
|
9 |
# This program is distributed in the hope that it will be useful,
|
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
# GNU General Public License for more details.
|
|
13 |
#
|
|
14 |
# You should have received a copy of the GNU General Public License
|
|
15 |
# along with this program; if not, write to the Free Software
|
|
16 |
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17 |
||
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
18 |
"""User and group filesystem management helpers."""
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
19 |
|
1197
by Matt Giuca
ivle.chat, ivle.database, ivle.makeuser: Replaced use of md5 library with |
20 |
import hashlib |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
21 |
import os |
22 |
import stat |
|
23 |
import shutil |
|
24 |
import time |
|
25 |
import uuid |
|
26 |
import warnings |
|
27 |
import logging |
|
1239
by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call. |
28 |
import subprocess |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
29 |
|
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
30 |
import ivle.config |
31 |
from ivle.database import ProjectGroup, User |
|
1080.1.44
by William Grant
ivle.makeuser: Port rebuild_svn_group_config() to Storm. |
32 |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
33 |
def chown_to_webserver(filename): |
1239
by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call. |
34 |
"""chown a directory and its contents to the web server.
|
35 |
||
36 |
Recursively chowns a file or directory so the web server user owns it.
|
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
37 |
Assumes root.
|
38 |
"""
|
|
1239
by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call. |
39 |
subprocess.call(['chown', '-R', 'www-data:www-data', filename]) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
40 |
|
41 |
def make_svn_repo(path, throw_on_error=True): |
|
1239
by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call. |
42 |
"""Create a Subversion repository at the given path."""
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
43 |
try: |
1239
by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call. |
44 |
res = subprocess.call(['svnadmin', 'create', path]) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
45 |
if res != 0 and throw_on_error: |
46 |
raise Exception("Cannot create repository: %s" % path) |
|
47 |
except Exception, exc: |
|
48 |
print repr(exc) |
|
49 |
if throw_on_error: |
|
50 |
raise
|
|
51 |
||
52 |
chown_to_webserver(path) |
|
53 |
||
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
54 |
def rebuild_svn_config(store, config): |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
55 |
"""Build the complete SVN configuration file.
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
56 |
|
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
57 |
@param config: An ivle.config.Config object.
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
58 |
"""
|
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
59 |
users = store.find(User) |
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
60 |
conf_name = config['paths']['svn']['conf'] |
61 |
temp_name = conf_name + ".new" |
|
62 |
f = open(temp_name, "w") |
|
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
63 |
f.write("""\ |
64 |
# IVLE SVN repository authorisation configuration
|
|
65 |
# Generated: %(time)s |
|
66 |
""" % {'time': time.asctime()}) |
|
67 |
||
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
68 |
for u in users: |
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
69 |
f.write(""" |
70 |
[%(login)s:/] |
|
71 |
%(login)s = rw |
|
72 |
""" % {'login': u.login}) |
|
73 |
||
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
74 |
f.close() |
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
75 |
os.rename(temp_name, conf_name) |
76 |
chown_to_webserver(conf_name) |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
77 |
|
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
78 |
def rebuild_svn_group_config(store, config): |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
79 |
"""Build the complete SVN configuration file for groups
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
80 |
|
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
81 |
@param config: An ivle.config.Config object.
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
82 |
"""
|
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
83 |
conf_name = config['paths']['svn']['group_conf'] |
84 |
temp_name = conf_name + ".new" |
|
85 |
f = open(temp_name, "w") |
|
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
86 |
|
87 |
f.write("""\ |
|
88 |
# IVLE SVN group repository authorisation configuration
|
|
89 |
# Generated: %(time)s |
|
90 |
||
91 |
""" % {'time': time.asctime()}) |
|
92 |
||
1080.1.44
by William Grant
ivle.makeuser: Port rebuild_svn_group_config() to Storm. |
93 |
for group in store.find(ProjectGroup): |
94 |
offering = group.project_set.offering |
|
95 |
reponame = "_".join([offering.subject.short_name, |
|
96 |
offering.semester.year, |
|
97 |
offering.semester.semester, |
|
98 |
group.name]) |
|
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
99 |
|
100 |
f.write("[%s:/]\n" % reponame) |
|
1080.1.44
by William Grant
ivle.makeuser: Port rebuild_svn_group_config() to Storm. |
101 |
for user in group.members: |
102 |
f.write("%s = rw\n" % user.login) |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
103 |
f.write("\n") |
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
104 |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
105 |
f.close() |
1229
by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a |
106 |
os.rename(temp_name, conf_name) |
107 |
chown_to_webserver(conf_name) |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
108 |
|
1230
by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument. |
109 |
def make_svn_auth(store, login, config, throw_on_error=True): |
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
110 |
"""Create a Subversion password for a user.
|
111 |
||
112 |
Generates a new random Subversion password, and assigns it to the user.
|
|
113 |
The password is added to Apache's Subversion authentication file.
|
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
114 |
"""
|
1230
by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument. |
115 |
# filename is, eg, /var/lib/ivle/svn/ivle.auth
|
116 |
filename = config['paths']['svn']['auth_ivle'] |
|
1197
by Matt Giuca
ivle.chat, ivle.database, ivle.makeuser: Replaced use of md5 library with |
117 |
passwd = hashlib.md5(uuid.uuid4().bytes).hexdigest() |
1230
by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument. |
118 |
if os.path.exists(filename): |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
119 |
create = "" |
120 |
else: |
|
121 |
create = "c" |
|
122 |
||
1242
by William Grant
Use some multiline strings to make ivle.makeuser prettier. |
123 |
user = User.get_by_login(store, login) |
1080.1.7
by matt.giuca
The new ivle.database.User class is now used in Request and usrmgt, which |
124 |
user.svn_pass = unicode(passwd) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
125 |
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
126 |
res = subprocess.call(['htpasswd', '-%smb' % create, |
127 |
filename, login, passwd]) |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
128 |
if res != 0 and throw_on_error: |
129 |
raise Exception("Unable to create ivle-auth for %s" % login) |
|
130 |
||
131 |
# Make sure the file is owned by the web server
|
|
132 |
if create == "c": |
|
1230
by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument. |
133 |
chown_to_webserver(filename) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
134 |
|
135 |
return passwd |
|
136 |
||
1231
by Matt Giuca
ivle.makeuser: make_jail now requires a config argument. |
137 |
def make_jail(user, config, force=True): |
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
138 |
"""Create or update a user's jail.
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
139 |
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
140 |
Only the user-specific parts of the jail are created here - everything
|
141 |
else is expected to be part of another aufs branch.
|
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
142 |
|
143 |
Returns the path to the user's home directory.
|
|
144 |
||
145 |
Chowns the user's directory within the jail to the given UID.
|
|
146 |
||
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
147 |
@param force: If False, raise an exception if the user already has a jail.
|
148 |
If True (default), rebuild the jail preserving /home.
|
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
149 |
"""
|
150 |
# MUST run as root or some of this may fail
|
|
151 |
if os.getuid() != 0: |
|
152 |
raise Exception("Must run make_jail as root") |
|
153 |
||
154 |
# tempdir is for putting backup homes in
|
|
1231
by Matt Giuca
ivle.makeuser: make_jail now requires a config argument. |
155 |
jail_src_base = config['paths']['jails']['src'] |
156 |
tempdir = os.path.join(jail_src_base, '__temp__') |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
157 |
if not os.path.exists(tempdir): |
158 |
os.makedirs(tempdir) |
|
159 |
elif not os.path.isdir(tempdir): |
|
160 |
os.unlink(tempdir) |
|
161 |
os.mkdir(tempdir) |
|
1231
by Matt Giuca
ivle.makeuser: make_jail now requires a config argument. |
162 |
userdir = os.path.join(jail_src_base, user.login) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
163 |
homedir = os.path.join(userdir, 'home') |
1080.1.19
by me at id
ivle.makeuser.make_jail: Just take an ivle.database.User, rather than some |
164 |
userhomedir = os.path.join(homedir, user.login) # Return value |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
165 |
|
166 |
if os.path.exists(userdir): |
|
167 |
if not force: |
|
168 |
raise Exception("User's jail already exists") |
|
169 |
# User jail already exists. Blow it away but preserve their home
|
|
170 |
# directory. It should be all that is there anyway, but you never
|
|
171 |
# know!
|
|
172 |
# Ignore warnings about the use of tmpnam
|
|
173 |
warnings.simplefilter('ignore') |
|
174 |
homebackup = os.tempnam(tempdir) |
|
175 |
warnings.resetwarnings() |
|
1186
by Matt Giuca
ivle.makeuser: Fixed odd code which would create the home directory, then |
176 |
# Back up the /home directory, delete the entire jail, recreate the
|
177 |
# jail directory tree, then copy the /home back
|
|
178 |
# NOTE that shutil.move changed in Python 2.6, it now moves a
|
|
179 |
# directory INTO the target (like `mv`), which it didn't use to do.
|
|
180 |
# This code works regardless.
|
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
181 |
shutil.move(homedir, homebackup) |
182 |
shutil.rmtree(userdir) |
|
1186
by Matt Giuca
ivle.makeuser: Fixed odd code which would create the home directory, then |
183 |
os.makedirs(userdir) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
184 |
shutil.move(homebackup, homedir) |
185 |
# Change the ownership of all the files to the right unixid
|
|
186 |
logging.debug("chown %s's home directory files to uid %d" |
|
1080.1.19
by me at id
ivle.makeuser.make_jail: Just take an ivle.database.User, rather than some |
187 |
%(user.login, user.unixid)) |
1114
by William Grant
ivle.makeuser.make_jail() no longer uses os.walk() to recursively set |
188 |
os.spawnvp(os.P_WAIT, 'chown', ['chown', '-R', '%d:%d' % (user.unixid, |
189 |
user.unixid), userhomedir]) |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
190 |
else: |
191 |
# No user jail exists
|
|
192 |
# Set up the user's home directory
|
|
193 |
os.makedirs(userhomedir) |
|
194 |
# Chown (and set the GID to the same as the UID).
|
|
1080.1.19
by me at id
ivle.makeuser.make_jail: Just take an ivle.database.User, rather than some |
195 |
os.chown(userhomedir, user.unixid, user.unixid) |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
196 |
# Chmod to rwxr-xr-x (755)
|
197 |
os.chmod(userhomedir, 0755) |
|
198 |
||
1232
by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument. |
199 |
make_ivle_conf(user.login, userdir, user.svn_pass, config) |
1231
by Matt Giuca
ivle.makeuser: make_jail now requires a config argument. |
200 |
make_etc_passwd(user.login, userdir, config['paths']['jails']['template'], |
201 |
user.unixid) |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
202 |
|
203 |
return userhomedir |
|
204 |
||
1232
by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument. |
205 |
def make_ivle_conf(username, user_jail_dir, svn_pass, sys_config): |
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
206 |
"""Generate an ivle.conf for a user's jail.
|
207 |
||
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
208 |
Creates (overwriting any existing file, and creating directories) a
|
1187
by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead. |
209 |
file /etc/ivle/ivle.conf in a given user's jail.
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
210 |
|
1232
by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument. |
211 |
@param username: Username.
|
1236
by Matt Giuca
Fixed docstring in makeuser (don't refer to ivle.conf). |
212 |
@param user_jail_dir: User's jail dir, ie. ['jails']['src'] + username
|
1232
by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument. |
213 |
@param svn_pass: User's SVN password.
|
214 |
@param sys_config: An ivle.config.Config object (the system-wide config).
|
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
215 |
"""
|
1187
by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead. |
216 |
conf_path = os.path.join(user_jail_dir, "etc/ivle/ivle.conf") |
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
217 |
os.makedirs(os.path.dirname(conf_path)) |
218 |
||
1092.1.1
by William Grant
[Uber-commit of holiday work because I lacked a local copy of the branch.] |
219 |
# In the "in-jail" version of conf, we don't need MOST of the details
|
220 |
# (it would be a security risk to have them here).
|
|
1187
by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead. |
221 |
# So we just write root_dir.
|
222 |
conf_obj = ivle.config.Config(blank=True) |
|
223 |
conf_obj.filename = conf_path |
|
1232
by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument. |
224 |
conf_obj['urls']['root'] = sys_config['urls']['root'] |
225 |
conf_obj['urls']['public_host'] = sys_config['urls']['public_host'] |
|
226 |
conf_obj['urls']['svn_addr'] = sys_config['urls']['svn_addr'] |
|
1187
by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead. |
227 |
conf_obj['user_info']['login'] = username |
228 |
conf_obj['user_info']['svn_pass'] = svn_pass |
|
229 |
conf_obj.write() |
|
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
230 |
|
231 |
# Make this file world-readable
|
|
232 |
# (chmod 644 conf_path)
|
|
233 |
os.chmod(conf_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP |
|
234 |
| stat.S_IROTH) |
|
235 |
||
236 |
def make_etc_passwd(username, user_jail_dir, template_dir, unixid): |
|
1240
by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings |
237 |
"""Create a passwd file for a user's jail.
|
238 |
||
1079
by William Grant
Merge setup-refactor branch. This completely breaks existing installations; |
239 |
Creates /etc/passwd in the given user's jail. This will be identical to
|
240 |
that in the template jail, except for the added entry for this user.
|
|
241 |
"""
|
|
242 |
template_passwd_path = os.path.join(template_dir, "etc/passwd") |
|
243 |
passwd_path = os.path.join(user_jail_dir, "etc/passwd") |
|
244 |
passwd_dir = os.path.dirname(passwd_path) |
|
245 |
if not os.path.exists(passwd_dir): |
|
246 |
os.makedirs(passwd_dir) |
|
247 |
shutil.copy(template_passwd_path, passwd_path) |
|
248 |
passwd_file = open(passwd_path, 'a') |
|
249 |
passwd_file.write('%s:x:%d:%d::/home/%s:/bin/bash' |
|
250 |
% (username, unixid, unixid, username)) |
|
251 |
passwd_file.close() |