Changeset 2044 for branches/fc15-dev/host/credit-card
- Timestamp:
- Nov 11, 2011, 1:07:59 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/fc15-dev/host/credit-card/host.py
r1999 r2044 1 1 import os 2 2 import optparse 3 import logging4 3 import socket 5 4 import tempfile 6 5 import shutil 7 6 import errno 7 import csv 8 8 9 9 import shell … … 13 13 # XXX test server and wizard server 14 14 15 ROOT_UID = 0 16 SIGNUP_UID = 102 17 SQL_UID = 537704221 18 FEDORA_DS_UID = 103 # XXX ACTUALLY CONFIGURE SERVERS TO USE THIS 19 LOGVIEW_UID = 501 # XXX Autogenerated, I don't like this... 15 # UIDs (sketchy): 16 # signup 102 17 # fedora-ds 103 (sketchy, not true for b-b) 18 # logview 501 (really sketchy, since it's in the dynamic range) 20 19 20 # Works for passwd and group, but be careful! They're different things! 21 def lookup(filename): 22 # Super-safe to assume and volume IDs (expensive to check) 23 r = { 24 'root': 0, 25 'sql': 537704221, 26 } 27 with open(filename, 'rb') as f: 28 reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE) 29 for row in reader: 30 r[row[0]] = int(row[2]) 31 return r 32 33 # Format here assumes that we always chmod $USER:$USER ... 34 # but note the latter refers to group... 21 35 COMMON_CREDS = [ 22 ( ROOT_UID, 0o600, 'root/.bashrc'),23 ( ROOT_UID, 0o600, 'root/.screenrc'),24 ( ROOT_UID, 0o600, 'root/.ssh/authorized_keys'),25 ( ROOT_UID, 0o600, 'root/.ssh/authorized_keys2'),26 ( ROOT_UID, 0o600, 'root/.vimrc'),27 ( ROOT_UID, 0o600, 'root/.k5login'),36 ('root', 0o600, 'root/.bashrc'), 37 ('root', 0o600, 'root/.screenrc'), 38 ('root', 0o600, 'root/.ssh/authorized_keys'), 39 ('root', 0o600, 'root/.ssh/authorized_keys2'), 40 ('root', 0o600, 'root/.vimrc'), 41 ('root', 0o600, 'root/.k5login'), 28 42 # punted /root/.ssh/known_hosts 29 43 30 # XXX must be created in Kickstart31 ( LOGVIEW_UID, 0o600, 'home/logview/.k5login'),44 # XXX user must be created in Kickstart 45 ('logview', 0o600, 'home/logview/.k5login'), 32 46 ] 33 47 34 48 COMMON_PROD_CREDS = [ # important: no leading slashes! 35 ( ROOT_UID, 0o600, 'root/.ldapvirc'),36 ( ROOT_UID, 0o600, 'etc/ssh/ssh_host_dsa_key'),37 ( ROOT_UID, 0o600, 'etc/ssh/ssh_host_key'),38 ( ROOT_UID, 0o600, 'etc/ssh/ssh_host_rsa_key'),39 ( ROOT_UID, 0o600, 'etc/pki/tls/private/scripts.key'),40 ( ROOT_UID, 0o600, 'etc/whoisd-password'),41 ( ROOT_UID, 0o600, 'etc/daemon.keytab'),49 ('root', 0o600, 'root/.ldapvirc'), 50 ('root', 0o600, 'etc/ssh/ssh_host_dsa_key'), 51 ('root', 0o600, 'etc/ssh/ssh_host_key'), 52 ('root', 0o600, 'etc/ssh/ssh_host_rsa_key'), 53 ('root', 0o600, 'etc/pki/tls/private/scripts.key'), 54 ('root', 0o600, 'etc/whoisd-password'), 55 ('root', 0o600, 'etc/daemon.keytab'), 42 56 43 ( ROOT_UID, 0o644, 'etc/ssh/ssh_host_dsa_key.pub'),44 ( ROOT_UID, 0o644, 'etc/ssh/ssh_host_key.pub'),45 ( ROOT_UID, 0o644, 'etc/ssh/ssh_host_rsa_key.pub'),57 ('root', 0o644, 'etc/ssh/ssh_host_dsa_key.pub'), 58 ('root', 0o644, 'etc/ssh/ssh_host_key.pub'), 59 ('root', 0o644, 'etc/ssh/ssh_host_rsa_key.pub'), 46 60 47 ( SQL_UID, 0o600, 'etc/sql-mit-edu.cfg.php'),48 ( SIGNUP_UID, 0o600, 'etc/signup-ldap-pw'),61 ('sql', 0o600, 'etc/sql-mit-edu.cfg.php'), 62 ('signup', 0o600, 'etc/signup-ldap-pw'), 49 63 ] 50 64 51 65 MACHINE_PROD_CREDS = [ 52 66 # XXX NEED TO CHECK THAT THESE ARE SENSIBLE 53 ( ROOT_UID, 0o600, 'etc/krb5.keytab'),54 ( FEDORA_DS_UID, 0o600, 'etc/dirsrv/keytab')67 ('root', 0o600, 'etc/krb5.keytab'), 68 ('fedora-ds', 0o600, 'etc/dirsrv/keytab') 55 69 ] 56 70 57 def mkdir_p(path): 71 def mkdir_p(path): # it's like mkdir -p 58 72 try: 59 73 os.makedirs(path) 60 except OSError as e xc: # Python >2.561 if e xc.errno == errno.EEXIST:74 except OSError as e: 75 if e.errno == errno.EEXIST: 62 76 pass 63 77 else: raise 64 78 79 # XXX This code is kind of dangerous, because we are directly using the 80 # kernel modules to manipulate possibly untrusted disk images. This 81 # means that if an attacker can corrupt the disk, and exploit a problem 82 # in the kernel vfs driver, he can escalate a guest root exploit 83 # to a host root exploit. Ultimately we should use libguestfs 84 # which makes this attack harder to pull off, but at the time of writing 85 # squeeze didn't package libguestfs. 86 # 87 # We try to minimize attack surface by explicitly specifying the 88 # expected filesystem type. 65 89 class WithMount(object): 66 90 """Context for running code with an extra mountpoint.""" 67 91 guest = None 92 types = None # comma separated, like the mount argument -t 68 93 mount = None 69 94 dev = None 70 def __init__(self, guest ):95 def __init__(self, guest, types): 71 96 self.guest = guest 97 self.types = types 72 98 def __enter__(self): 73 99 self.dev = "/dev/%s/%s-root" % (HOST, self.guest) … … 81 107 self.mount = tempfile.mkdtemp("-%s" % self.guest, 'vm-', '/mnt') # no trailing slash 82 108 try: 83 shell.call("mount", mapper, self.mount)109 shell.call("mount", "--types", self.types, mapper, self.mount) 84 110 except: 85 111 os.rmdir(self.mount) … … 90 116 91 117 return self.mount 92 def __exit__(self, *args):118 def __exit__(self, _type, _value, _traceback): 93 119 shell.call("umount", self.mount) 94 120 os.rmdir(self.mount) … … 96 122 97 123 def main(): 98 usage = """usage: %prog [ ARGS]"""124 usage = """usage: %prog [push|pull|pull-common] GUEST""" 99 125 100 126 parser = optparse.OptionParser(usage) 101 _, args = parser.parse_args() 127 # ext3 will probably supported for a while yet and a pretty 128 # reasonable thing to always try 129 parser.add_option('-t', '--types', dest="types", default="ext4,ext3", 130 help="filesystem type(s)") 131 parser.add_option('--creds-dir', dest="creds_dir", default="/root/creds", 132 help="directory to store/fetch credentials in") 133 options, args = parser.parse_args() 102 134 103 creds = "/root/creds" # XXX check exists, check owned by root 104 # make an option 105 if not os.path.isdir(creds): 106 raise Exception("/root/creds does not exist") 135 if not os.path.isdir(options.creds_dir): 136 raise Exception("/root/creds does not exist") # XXX STRING 137 # XXX check owned by root and appropriately chmodded 107 138 108 139 os.umask(0o077) # overly restrictive 109 140 110 # XXX error handling111 112 141 if len(args) != 2: 142 parser.print_help() 113 143 raise Exception("Wrong number of arguments") 114 144 … … 116 146 guest = args[1] 117 147 118 with WithMount(guest) as tmp_mount: 148 with WithMount(guest, options.types) as tmp_mount: 149 uid_lookup = lookup("%s/etc/passwd" % tmp_mount) 150 gid_lookup = lookup("%s/etc/group" % tmp_mount) 119 151 def push_files(files, type): 120 for (ugid, perms, f) in files: 121 # assumes directories exist 152 for (usergroup, perms, f) in files: 122 153 dest = "%s/%s" % (tmp_mount, f) 154 mkdir_p(os.path.dirname(dest)) # useful for .ssh 123 155 # assuming OK to overwrite 124 shutil.copyfile("%s/%s/%s" % (creds, type, f), dest) 125 os.chown(dest, ugid, ugid) 126 os.chmod(dest, perms) 156 # XXX we could compare the files before doing anything... 157 shutil.copyfile("%s/%s/%s" % (options.creds_dir, type, f), dest) 158 try: 159 os.chown(dest, uid_lookup[usergroup], gid_lookup[usergroup]) 160 os.chmod(dest, perms) 161 except: 162 # never ever leave un-chowned files lying around 163 os.unlink(dest) 164 raise 127 165 def pull_files(files, type): 128 166 for (_, _, f) in files: 129 dest = "%s/%s/%s" % ( creds, type, f)167 dest = "%s/%s/%s" % (options.creds_dir, type, f) 130 168 mkdir_p(os.path.dirname(dest)) 131 169 # error if doesn't exist 132 170 shutil.copyfile("%s/%s" % (tmp_mount, f), dest) 133 171 134 # push case135 172 if command == "push": 136 173 push_files(COMMON_CREDS, 'common') … … 138 175 push_files(MACHINE_PROD_CREDS, 'machine/%s' % guest) 139 176 elif command == "pull": 140 # check if /root/creds exists141 177 pull_files(MACHINE_PROD_CREDS, 'machine/%s' % guest) 142 178 elif command == "pull-common":
Note: See TracChangeset
for help on using the changeset viewer.