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

« back to all changes in this revision

Viewing changes to bin/ivle-buildjail

Added module ivle.config, which takes care of some work interfacing with
    configobj, including searching for the file and opening the object.
ivle.conf.conf now uses this instead of having its own search.

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
22
21
import sys
23
22
import shutil
24
23
 
25
 
import ivle.config
26
 
import ivle.jailbuilder.debian
27
 
 
28
 
class UnsafeJail(Exception):
29
 
    pass
 
24
import ivle.conf
30
25
 
31
26
usage = """usage: %prog [options]
32
27
(requires root)
33
28
Builds or updates the base IVLE jail."""
34
29
 
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
30
# Parse arguments
44
31
parser = optparse.OptionParser(usage)
45
32
parser.add_option("-r", "--recreate",
46
33
    action="store_true", dest="recreate",
47
34
    help='''Completely recreate the jail - don't just update its IVLE code.
48
35
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
36
parser.add_option("-m", "--mirror",
53
37
    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)
 
38
    help="Sets the apt mirror used when recreating the jail.")
59
39
(options, args) = parser.parse_args(sys.argv)
60
40
 
61
41
if os.geteuid() != 0:
62
42
    print >> sys.stderr, "Must be root to run buildjail."
63
43
    sys.exit(1)
64
44
 
65
 
if not options.recreate and not os.path.exists(build_path):
 
45
if not options.recreate and not os.path.exists(ivle.conf.jail_system_build):
66
46
    print >> sys.stderr, "No jail exists -- please rerun with -r."
67
47
    sys.exit(1)
68
48
 
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
49
if options.recreate:
75
 
    options.upgrade = True
76
 
 
77
50
    # Create the jail and its subdirectories
78
51
    # Note: Other subdirs will be made by copying files
79
52
    if options.apt_mirror is not None:
80
53
        os.environ['MIRROR'] = options.apt_mirror
81
54
 
82
 
    os.system('rm -rf --one-file-system ' + build_path)
83
 
    ivle.jailbuilder.debian.debootstrap_create_jail(conf['jail']['suite'],
84
 
              build_path, mirror=options.apt_mirror)
85
 
 
86
 
    ivle.jailbuilder.debian.apt_update_cache(build_path)
87
 
    # Minimal required packages
88
 
    ivle.jailbuilder.debian.apt_install(build_path,
89
 
            ['python2.5', 'python-cjson', 'python-svn', 'python-configobj'])
90
 
 
91
 
    ivle.jailbuilder.debian.apt_clean(build_path)
92
 
 
93
 
if options.upgrade:
94
 
    # Run apt-get update, apt-get upgrade and apt-get clean.
95
 
    ivle.jailbuilder.debian.mangle_sources_list(build_path, clobber=True)
96
 
    ivle.jailbuilder.debian.mangle_sources_list(build_path, lines=[
97
 
            'deb %s %s%s %s' % (options.apt_mirror, conf['jail']['suite'],
98
 
                                pocket, ' '.join(['main', 'universe']))
99
 
            for pocket in ('', '-updates', '-security')])
100
 
 
101
 
    # Add any extra site apt sources.
102
 
    if conf['jail']['extra_sources']:
103
 
        ivle.jailbuilder.debian.mangle_sources_list(build_path,
104
 
                  conf['jail']['extra_sources'])
105
 
 
106
 
    # Add any extra site apt keys.
107
 
    if conf['jail']['extra_keys']:
108
 
        ivle.jailbuilder.debian.apt_add_key(build_path,
109
 
                                            conf['jail']['extra_keys'])
110
 
 
111
 
    ivle.jailbuilder.debian.apt_update_cache(build_path)
112
 
    ivle.jailbuilder.debian.apt_upgrade(build_path)
113
 
 
114
 
    # Install any extra site packages.
115
 
    if conf['jail']['extra_packages']:
116
 
        ivle.jailbuilder.debian.apt_install(build_path,
117
 
                  conf['jail']['extra_packages'])
118
 
 
119
 
    ivle.jailbuilder.debian.apt_clean(build_path)
120
 
 
121
 
    # Configure locales to allow en_US.UTF-8 (which IVLE uses)
122
 
    ivle.jailbuilder.debian._execute_in_chroot(build_path,
123
 
        ['locale-gen', 'en_US.UTF-8'])
124
 
 
125
 
if conf['jail']['devmode']:
126
 
    # Copy all console and operating system files into the jail
127
 
    services_path = os.path.join(conf['paths']['share'], 'services')
128
 
    jail_services_path = os.path.join(build_path, services_path[1:])
129
 
    if os.path.exists(jail_services_path):
130
 
        shutil.rmtree(jail_services_path)
131
 
    shutil.copytree(services_path, jail_services_path)
132
 
 
133
 
    # Also copy the IVLE lib directory into the jail
134
 
    # This is necessary for running certain services
135
 
 
136
 
    # ivle_site_packages is the IVLE install location outside the jail
137
 
    ivle_site_packages = os.path.dirname(ivle.__file__)
138
 
 
139
 
    if options.python_site_packages is None:
140
 
        # Get the site packages from the IVLE install location *OUTSIDE* the
141
 
        # jail. Warning! This only works if you have the same Python site
142
 
        # packages directory inside and out (ie. same Python version).
143
 
        # If not, you should use --python-site-packages.
144
 
        jail_site_packages = os.path.join(build_path, ivle_site_packages[1:])
145
 
    else:
146
 
        # User-specified site packages
147
 
        jail_site_packages = os.path.join(build_path,
148
 
                                options.python_site_packages[1:], "ivle")
149
 
    if os.path.exists(jail_site_packages):
150
 
        shutil.rmtree(jail_site_packages)
151
 
    shutil.copytree(ivle_site_packages, jail_site_packages)
152
 
 
153
 
    # And finally copy in /etc/hosts, /etc/resolv.conf and /etc/hostname,
154
 
    # so name resolution is less unlikely to work.
155
 
    shutil.copy(
156
 
        '/etc/resolv.conf', os.path.join(build_path, 'etc/resolv.conf'))
157
 
    shutil.copy('/etc/hosts', os.path.join(build_path, 'etc/hosts'))
158
 
    shutil.copy('/etc/hostname', os.path.join(build_path, 'etc/hostname'))
159
 
 
160
 
# Make /tmp and /var/lock un-world-writable. /tmp will be mounted over,
161
 
# and /var/{lock,tmp} should die.
162
 
for path in ('tmp', 'var/lock', 'var/tmp'):
163
 
    path = os.path.join(build_path, path)
164
 
    os.chmod(path, os.stat(path).st_mode & ~stat.S_IWOTH)
165
 
 
166
 
# Verify that nothing in the jail is world-writable.
167
 
# We don't want students to write into places that others can see.
168
 
try:
169
 
    for path, dirs, files in os.walk(build_path):
170
 
        for dname in dirs:
171
 
            d = os.path.join(path, dname)
172
 
            if os.path.islink(d):
173
 
                continue
174
 
            if os.stat(d).st_mode & stat.S_IWOTH:
175
 
                raise UnsafeJail(d)
176
 
 
177
 
        for fname in files:
178
 
            f = os.path.join(path, fname)
179
 
            if os.path.islink(f):
180
 
                continue
181
 
            if os.stat(f).st_mode & stat.S_IWOTH:
182
 
                if (os.path.dirname(f) == os.path.join(build_path, 'dev') and
183
 
                    os.path.basename(f) in ('ptmx', 'null', 'tty', 'full', 'zero',
184
 
                                            'random', 'urandom')
185
 
                    ):
186
 
                    continue
187
 
                raise UnsafeJail(f)
188
 
except UnsafeJail, e:
189
 
    print >> sys.stderr,"""Error: Jail contains world writable path: '%s'.
190
 
This is a security vulnerability as jail template contents are shared between 
191
 
users. Please either make this path world unwriteable or remove it from the 
192
 
jail."""%str(e)
193
 
    sys.exit(1)
194
 
 
195
 
# Copy jail template build to actual jail template
196
 
template_path = conf['paths']['jails']['template']
 
55
    # XXX: buildjail.sh should be reimplemented in Python, with its envvars
 
56
    # turned into config options.
 
57
    if os.spawnvp(os.P_WAIT, 'setup/buildjail.sh',
 
58
                  ['setup/buildjail.sh', ivle.conf.jail_system_build]) != 0:
 
59
        print >> sys.stderr, "Jail creation failed."
 
60
        sys.exit(1)
 
61
 
 
62
# Copy all console and operating system files into the jail
 
63
services_path = os.path.join(ivle.conf.share_path, 'services')
 
64
jail_services_path = os.path.join(ivle.conf.jail_system_build,
 
65
                                  services_path[1:])
 
66
if os.path.exists(jail_services_path):
 
67
    shutil.rmtree(jail_services_path)
 
68
shutil.copytree(services_path, jail_services_path)
 
69
 
 
70
# Also copy the IVLE lib directory into the jail
 
71
# This is necessary for running certain services
 
72
ivle_site_packages = os.path.join(ivle.conf.python_site_packages, 'ivle')
 
73
jail_site_packages = os.path.join(ivle.conf.jail_system_build,
 
74
                                  ivle_site_packages[1:])
 
75
if os.path.exists(jail_site_packages):
 
76
    shutil.rmtree(jail_site_packages)
 
77
shutil.copytree(ivle_site_packages, jail_site_packages)
 
78
 
 
79
# IMPORTANT: ivle/conf/conf.py contains details which could compromise security
 
80
# if left in the jail (such as the DB password). We delete it now! It would be
 
81
# shadowed by the per-user conf.py anyway, but it's best to be safe.
 
82
os.unlink(os.path.join(jail_site_packages, 'conf/conf.py'))
 
83
# XXX: Shouldn't copy the compiled files at all, but compile them in the jail!
 
84
os.unlink(os.path.join(jail_site_packages, 'conf/conf.pyc'))
 
85
 
197
86
if os.spawnvp(os.P_WAIT, 'rsync', ['rsync', '-a', '--delete',
198
 
              build_path + '/', template_path]) != 0:
 
87
              ivle.conf.jail_system_build + '/', ivle.conf.jail_system]) != 0:
199
88
    print >> sys.stderr, "Jail copying failed."
200
89
    sys.exit(1)
201
90
 
202
 
# Now mangle things a bit, so we can bind-mount the user bits in.
203
 
# /etc/passwd and /etc/ivle/ivle.conf need to be symlinks to somewhere in /home
204
 
 
205
 
os.rename(os.path.join(template_path, 'etc/passwd'),
206
 
          os.path.join(template_path, 'home/.passwd')
207
 
          )
208
 
os.symlink('../home/.passwd', os.path.join(template_path, 'etc/passwd'))
209
 
 
210
 
os.makedirs(os.path.join(template_path, "etc/ivle"))
211
 
os.symlink('../../home/.ivle.conf',
212
 
           os.path.join(template_path, "etc/ivle/ivle.conf"))