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

« back to all changes in this revision

Viewing changes to bin/ivle-buildjail

  • Committer: William Grant
  • Date: 2010-07-28 04:13:05 UTC
  • mfrom: (1801.1.2 die-cjson-die)
  • Revision ID: grantw@unimelb.edu.au-20100728041305-xwypm3cn1l1mnki1
Port from cjson to (simple)json.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
import optparse
20
20
import os
 
21
import stat
21
22
import sys
22
23
import shutil
23
24
 
24
 
import ivle.conf
25
25
import ivle.config
26
26
import ivle.jailbuilder.debian
27
27
 
 
28
class UnsafeJail(Exception):
 
29
    pass
 
30
 
28
31
usage = """usage: %prog [options]
29
32
(requires root)
30
33
Builds or updates the base IVLE jail."""
31
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
 
32
40
conf = ivle.config.Config()
33
 
build_path = ivle.conf.jail_system_build
 
41
build_path = conf['paths']['jails']['template_build']
34
42
 
35
43
# Parse arguments
36
44
parser = optparse.OptionParser(usage)
43
51
    help='''Apply any package updates in the jail.''')
44
52
parser.add_option("-m", "--mirror",
45
53
    action="store", dest="apt_mirror",
46
 
    help="Sets the apt mirror used when recreating the jail.")
 
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)
47
59
(options, args) = parser.parse_args(sys.argv)
48
60
 
49
61
if os.geteuid() != 0:
54
66
    print >> sys.stderr, "No jail exists -- please rerun with -r."
55
67
    sys.exit(1)
56
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
 
57
74
if options.recreate:
 
75
    options.upgrade = True
 
76
 
58
77
    # Create the jail and its subdirectories
59
78
    # Note: Other subdirs will be made by copying files
60
79
    if options.apt_mirror is not None:
61
80
        os.environ['MIRROR'] = options.apt_mirror
62
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
 
63
92
    os.system('rm -rf --one-file-system ' + build_path)
64
93
    ivle.jailbuilder.debian.debootstrap_create_jail(conf['jail']['suite'],
65
94
              build_path, mirror=options.apt_mirror)
66
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-simplejson', '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
 
67
111
    # Add any extra site apt sources.
68
112
    if conf['jail']['extra_sources']:
69
113
        ivle.jailbuilder.debian.mangle_sources_list(build_path,
75
119
                                            conf['jail']['extra_keys'])
76
120
 
77
121
    ivle.jailbuilder.debian.apt_update_cache(build_path)
78
 
    ivle.jailbuilder.debian.apt_install(build_path,
79
 
                        ['python2.5', 'python-cjson', 'python-svn'])
 
122
    ivle.jailbuilder.debian.apt_upgrade(build_path)
80
123
 
81
124
    # Install any extra site packages.
82
125
    if conf['jail']['extra_packages']:
85
128
 
86
129
    ivle.jailbuilder.debian.apt_clean(build_path)
87
130
 
88
 
if options.upgrade:
89
 
    # Run apt-get update, apt-get upgrade and apt-get clean.
90
 
    ivle.jailbuilder.debian.apt_update_cache(build_path)
91
 
    ivle.jailbuilder.debian.apt_upgrade(build_path)
92
 
    ivle.jailbuilder.debian.apt_clean(build_path)
 
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'])
93
134
 
94
135
if conf['jail']['devmode']:
95
136
    # Copy all console and operating system files into the jail
96
 
    services_path = os.path.join(ivle.conf.share_path, 'services')
 
137
    services_path = os.path.join(conf['paths']['share'], 'services')
97
138
    jail_services_path = os.path.join(build_path, services_path[1:])
98
139
    if os.path.exists(jail_services_path):
99
140
        shutil.rmtree(jail_services_path)
101
142
 
102
143
    # Also copy the IVLE lib directory into the jail
103
144
    # This is necessary for running certain services
104
 
    ivle_site_packages = os.path.join(ivle.conf.python_site_packages, 'ivle')
105
 
    jail_site_packages = os.path.join(build_path, ivle_site_packages[1:])
 
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")
106
159
    if os.path.exists(jail_site_packages):
107
160
        shutil.rmtree(jail_site_packages)
108
161
    shutil.copytree(ivle_site_packages, jail_site_packages)
109
162
 
110
 
    # IMPORTANT: ivle/conf/conf.py contains details which could compromise security
111
 
    # if left in the jail (such as the DB password). We delete it now! It would be
112
 
    # shadowed by the per-user conf.py anyway, but it's best to be safe.
113
 
    os.unlink(os.path.join(jail_site_packages, 'conf/conf.py'))
114
 
    # XXX: Shouldn't copy the compiled files at all, but compile them in the jail!
115
 
    os.unlink(os.path.join(jail_site_packages, 'conf/conf.pyc'))
116
 
 
 
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']
117
207
if os.spawnvp(os.P_WAIT, 'rsync', ['rsync', '-a', '--delete',
118
 
              build_path + '/', ivle.conf.jail_system]) != 0:
 
208
              build_path + '/', template_path]) != 0:
119
209
    print >> sys.stderr, "Jail copying failed."
120
210
    sys.exit(1)
121
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"))