~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to bin/ivle-buildjail

In the new framework handler, either write the exception message or use
Apache's. Previously any message present would simply be prepended to Apache's,
resulting in something very ugly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
# IVLE - Informatics Virtual Learning Environment
3
 
# Copyright (C) 2009 The University of Melbourne
4
 
#
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 
19
 
import optparse
20
 
import os
21
 
import stat
22
 
import sys
23
 
import shutil
24
 
 
25
 
import ivle.config
26
 
import ivle.jailbuilder.debian
27
 
 
28
 
class UnsafeJail(Exception):
29
 
    pass
30
 
 
31
 
usage = """usage: %prog [options]
32
 
(requires root)
33
 
Builds or updates the base IVLE jail."""
34
 
 
35
 
# Requires root
36
 
if os.getuid() != 0:
37
 
    print >> sys.stderr, "This script requires root privileges to run"
38
 
    sys.exit(1)
39
 
 
40
 
conf = ivle.config.Config()
41
 
build_path = conf['paths']['jails']['template_build']
42
 
 
43
 
# Parse arguments
44
 
parser = optparse.OptionParser(usage)
45
 
parser.add_option("-r", "--recreate",
46
 
    action="store_true", dest="recreate",
47
 
    help='''Completely recreate the jail - don't just update its IVLE code.
48
 
Be warned, this may download hundreds of megabytes!''')
49
 
parser.add_option("-u", "--upgrade",
50
 
    action="store_true", dest="upgrade",
51
 
    help='''Apply any package updates in the jail.''')
52
 
parser.add_option("-m", "--mirror",
53
 
    action="store", dest="apt_mirror",
54
 
    help="Sets the apt mirror.", default=conf['jail']['mirror'])
55
 
parser.add_option("--python-site-packages",
56
 
    action="store", dest="python_site_packages",
57
 
    help="Path to Python site packages directory inside the jail.",
58
 
    default=None)
59
 
(options, args) = parser.parse_args(sys.argv)
60
 
 
61
 
if os.geteuid() != 0:
62
 
    print >> sys.stderr, "Must be root to run buildjail."
63
 
    sys.exit(1)
64
 
 
65
 
if not options.recreate and not os.path.exists(build_path):
66
 
    print >> sys.stderr, "No jail exists -- please rerun with -r."
67
 
    sys.exit(1)
68
 
 
69
 
if (options.python_site_packages is not None and
70
 
    options.python_site_packages[:1] not in (os.path.sep, os.path.altsep)):
71
 
    print >> sys.stderr, "python-site-packages must be an absolute path."
72
 
    sys.exit(1)
73
 
 
74
 
if options.recreate:
75
 
    options.upgrade = True
76
 
 
77
 
    # Create the jail and its subdirectories
78
 
    # Note: Other subdirs will be made by copying files
79
 
    if options.apt_mirror is not None:
80
 
        os.environ['MIRROR'] = options.apt_mirror
81
 
 
82
 
    # Print a final warning to the user that this is a potentially-expensive
83
 
    # operation
84
 
    recreating = "Re-creating" if os.path.exists(build_path) else "Creating"
85
 
    print_mirror = options.apt_mirror or 'http://archive.ubuntu.com/ubuntu'
86
 
    print """%s jail from %s
87
 
Be warned, this may download hundreds of megabytes!
88
 
If this is the wrong source, please cancel now (note that it is too late to
89
 
save the existing jail; you will have to rebuild the jail from scratch now).\
90
 
""" % (recreating, print_mirror)
91
 
 
92
 
    os.system('rm -rf --one-file-system ' + build_path)
93
 
    ivle.jailbuilder.debian.debootstrap_create_jail(conf['jail']['suite'],
94
 
              build_path, mirror=options.apt_mirror)
95
 
 
96
 
    ivle.jailbuilder.debian.apt_update_cache(build_path)
97
 
    # Minimal required packages
98
 
    ivle.jailbuilder.debian.apt_install(build_path,
99
 
            ['python', 'python-cjson', 'python-svn', 'python-configobj'])
100
 
 
101
 
    ivle.jailbuilder.debian.apt_clean(build_path)
102
 
 
103
 
if options.upgrade:
104
 
    # Run apt-get update, apt-get upgrade and apt-get clean.
105
 
    ivle.jailbuilder.debian.mangle_sources_list(build_path, clobber=True)
106
 
    ivle.jailbuilder.debian.mangle_sources_list(build_path, lines=[
107
 
            'deb %s %s%s %s' % (options.apt_mirror, conf['jail']['suite'],
108
 
                                pocket, ' '.join(['main', 'universe']))
109
 
            for pocket in ('', '-updates', '-security')])
110
 
 
111
 
    # Add any extra site apt sources.
112
 
    if conf['jail']['extra_sources']:
113
 
        ivle.jailbuilder.debian.mangle_sources_list(build_path,
114
 
                  conf['jail']['extra_sources'])
115
 
 
116
 
    # Add any extra site apt keys.
117
 
    if conf['jail']['extra_keys']:
118
 
        ivle.jailbuilder.debian.apt_add_key(build_path,
119
 
                                            conf['jail']['extra_keys'])
120
 
 
121
 
    ivle.jailbuilder.debian.apt_update_cache(build_path)
122
 
    ivle.jailbuilder.debian.apt_upgrade(build_path)
123
 
 
124
 
    # Install any extra site packages.
125
 
    if conf['jail']['extra_packages']:
126
 
        ivle.jailbuilder.debian.apt_install(build_path,
127
 
                  conf['jail']['extra_packages'])
128
 
 
129
 
    ivle.jailbuilder.debian.apt_clean(build_path)
130
 
 
131
 
    # Configure locales to allow en_US.UTF-8 (which IVLE uses)
132
 
    ivle.jailbuilder.debian._execute_in_chroot(build_path,
133
 
        ['locale-gen', 'en_US.UTF-8'])
134
 
 
135
 
if conf['jail']['devmode']:
136
 
    # Copy all console and operating system files into the jail
137
 
    services_path = os.path.join(conf['paths']['share'], 'services')
138
 
    jail_services_path = os.path.join(build_path, services_path[1:])
139
 
    if os.path.exists(jail_services_path):
140
 
        shutil.rmtree(jail_services_path)
141
 
    shutil.copytree(services_path, jail_services_path)
142
 
 
143
 
    # Also copy the IVLE lib directory into the jail
144
 
    # This is necessary for running certain services
145
 
 
146
 
    # ivle_site_packages is the IVLE install location outside the jail
147
 
    ivle_site_packages = os.path.dirname(ivle.__file__)
148
 
 
149
 
    if options.python_site_packages is None:
150
 
        # Get the site packages from the IVLE install location *OUTSIDE* the
151
 
        # jail. Warning! This only works if you have the same Python site
152
 
        # packages directory inside and out (ie. same Python version).
153
 
        # If not, you should use --python-site-packages.
154
 
        jail_site_packages = os.path.join(build_path, ivle_site_packages[1:])
155
 
    else:
156
 
        # User-specified site packages
157
 
        jail_site_packages = os.path.join(build_path,
158
 
                                options.python_site_packages[1:], "ivle")
159
 
    if os.path.exists(jail_site_packages):
160
 
        shutil.rmtree(jail_site_packages)
161
 
    shutil.copytree(ivle_site_packages, jail_site_packages)
162
 
 
163
 
    # And finally copy in /etc/hosts, /etc/resolv.conf and /etc/hostname,
164
 
    # so name resolution is less unlikely to work.
165
 
    shutil.copy(
166
 
        '/etc/resolv.conf', os.path.join(build_path, 'etc/resolv.conf'))
167
 
    shutil.copy('/etc/hosts', os.path.join(build_path, 'etc/hosts'))
168
 
    shutil.copy('/etc/hostname', os.path.join(build_path, 'etc/hostname'))
169
 
 
170
 
# Make /tmp and /var/lock un-world-writable. /tmp will be mounted over,
171
 
# and /var/{lock,tmp} should die.
172
 
for path in ('tmp', 'var/lock', 'var/tmp'):
173
 
    path = os.path.join(build_path, path)
174
 
    os.chmod(path, os.stat(path).st_mode & ~stat.S_IWOTH)
175
 
 
176
 
# Verify that nothing in the jail is world-writable.
177
 
# We don't want students to write into places that others can see.
178
 
try:
179
 
    for path, dirs, files in os.walk(build_path):
180
 
        for dname in dirs:
181
 
            d = os.path.join(path, dname)
182
 
            if os.path.islink(d):
183
 
                continue
184
 
            if os.stat(d).st_mode & stat.S_IWOTH:
185
 
                raise UnsafeJail(d)
186
 
 
187
 
        for fname in files:
188
 
            f = os.path.join(path, fname)
189
 
            if os.path.islink(f):
190
 
                continue
191
 
            if os.stat(f).st_mode & stat.S_IWOTH:
192
 
                if (os.path.dirname(f) == os.path.join(build_path, 'dev') and
193
 
                    os.path.basename(f) in ('ptmx', 'null', 'tty', 'full', 'zero',
194
 
                                            'random', 'urandom')
195
 
                    ):
196
 
                    continue
197
 
                raise UnsafeJail(f)
198
 
except UnsafeJail, e:
199
 
    print >> sys.stderr,"""Error: Jail contains world writable path: '%s'.
200
 
This is a security vulnerability as jail template contents are shared between 
201
 
users. Please either make this path world unwriteable or remove it from the 
202
 
jail."""%str(e)
203
 
    sys.exit(1)
204
 
 
205
 
# Copy jail template build to actual jail template
206
 
template_path = conf['paths']['jails']['template']
207
 
if os.spawnvp(os.P_WAIT, 'rsync', ['rsync', '-a', '--delete',
208
 
              build_path + '/', template_path]) != 0:
209
 
    print >> sys.stderr, "Jail copying failed."
210
 
    sys.exit(1)
211
 
 
212
 
# Now mangle things a bit, so we can bind-mount the user bits in.
213
 
# /etc/passwd and /etc/ivle/ivle.conf need to be symlinks to somewhere in /home
214
 
 
215
 
os.rename(os.path.join(template_path, 'etc/passwd'),
216
 
          os.path.join(template_path, 'home/.passwd')
217
 
          )
218
 
os.symlink('../home/.passwd', os.path.join(template_path, 'etc/passwd'))
219
 
 
220
 
os.makedirs(os.path.join(template_path, "etc/ivle"))
221
 
os.symlink('../../home/.ivle.conf',
222
 
           os.path.join(template_path, "etc/ivle/ivle.conf"))