mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-25 19:10:10 +00:00
Have prototype cloning implemented
Go ahead and relabel all selinux content, ssh keys, grub, and efiboot entry.
This commit is contained in:
parent
22008f9dc9
commit
55302b74d9
@ -1,9 +1,12 @@
|
||||
#!/usr/bin/python3
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import shutil
|
||||
import socket
|
||||
import stat
|
||||
import struct
|
||||
import sys
|
||||
import subprocess
|
||||
@ -62,6 +65,8 @@ def fixup(rootdir, vols):
|
||||
fstab = tfile.read().split('\n')
|
||||
while not fstab[0]:
|
||||
fstab = fstab[1:]
|
||||
if os.path.exists(os.path.join(rootdir, '.autorelabel')):
|
||||
os.unlink(os.path.join(rootdir, '.autorelabel'))
|
||||
with open(fstabfile, 'w') as tfile:
|
||||
for tab in fstab:
|
||||
entry = tab.split()
|
||||
@ -82,19 +87,84 @@ def fixup(rootdir, vols):
|
||||
tab = '\t'.join(entry)
|
||||
tfile.write(tab + '\n')
|
||||
with open(os.path.join(rootdir, 'etc/hostname'), 'w') as nameout:
|
||||
nameout.write(socket.gethostname())
|
||||
#NEED: grub config, ssh (maybe in script that calls image2disk), hostname.
|
||||
#network interfaces, /etc/shadow of root's password, efibootmgr, various failed services
|
||||
# grub error:
|
||||
# error: ../../grub-core/commands/search.c:296:no such device:
|
||||
#^M7c1840f3-64e3-4fca-ae3d-aa5ae9333e32.
|
||||
#^Merror: ../../grub-core/commands/search.c:296:no such device:
|
||||
#^M7c1840f3-64e3-4fca-ae3d-aa5ae9333e32.
|
||||
#^Merror: ../../grub-core/commands/search.c:296:no such device: A278-1D2E.
|
||||
#^Merror: ../../grub-core/commands/search.c:296:no such device: A278-1D2E.
|
||||
|
||||
|
||||
|
||||
nameout.write(socket.gethostname() + '\n')
|
||||
selinuxconfig = os.path.join(rootdir, 'etc/selinux/config')
|
||||
policy = None
|
||||
if os.path.exists(selinuxconfig):
|
||||
with open(selinuxconfig) as cfgin:
|
||||
sec = cfgin.read().split('\n')
|
||||
for l in sec:
|
||||
l = l.split('#', 1)[0]
|
||||
if l.startswith('SELINUXTYPE='):
|
||||
_, policy = l.split('=')
|
||||
for sshkey in glob.glob(os.path.join(rootdir, 'etc/ssh/*_key*')):
|
||||
os.unlink(sshkey)
|
||||
for sshkey in glob.glob('/etc/ssh/*_key*'):
|
||||
newkey = os.path.join(rootdir, sshkey[1:])
|
||||
shutil.copy2(sshkey, newkey)
|
||||
finfo = os.stat(sshkey)
|
||||
os.chown(newkey, finfo[stat.ST_UID], finfo[stat.ST_GID])
|
||||
for ifcfg in glob.glob(os.path.join(rootdir, 'etc/sysconfig/network-scripts/*')):
|
||||
os.unlink(ifcfg)
|
||||
for ifcfg in glob.glob(os.path.join(rootdir, 'etc/NetworkManager/system-connections/*')):
|
||||
os.unlink(ifcfg)
|
||||
for ifcfg in glob.glob('/run/NetworkManager/system-connections/*'):
|
||||
newcfg = ifcfg.split('/')[-1]
|
||||
newcfg = os.path.join(rootdir, 'etc/NetworkManager/system-connections/{0}'.format(newcfg))
|
||||
shutil.copy2(ifcfg, newcfg)
|
||||
if policy:
|
||||
sys.stdout.write('Applying SELinux labeling...')
|
||||
sys.stdout.flush()
|
||||
subprocess.check_call(['setfiles', '-r', rootdir, os.path.join(rootdir, 'etc/selinux/{}/contexts/files/file_contexts'.format(policy)), rootdir])
|
||||
sys.stdout.write('Done\n')
|
||||
sys.stdout.flush()
|
||||
for metafs in ('proc', 'sys', 'dev'):
|
||||
subprocess.check_call(['mount', '-o', 'bind', '/{}'.format(metafs), os.path.join(rootdir, metafs)])
|
||||
with open(os.path.join(rootdir, 'etc/sysconfig/grub')) as defgrubin:
|
||||
defgrub = defgrubin.read().split('\n')
|
||||
with open(os.path.join(rootdir, 'etc/sysconfig/grub'), 'w') as defgrubout:
|
||||
for gline in defgrub:
|
||||
gline = gline.split()
|
||||
newline = []
|
||||
for ent in gline:
|
||||
if ent.startswith('resume=') or ent.startswith('rd.lvm.lv'):
|
||||
continue
|
||||
newline.append(ent)
|
||||
defgrubout.write(' '.join(newline) + '\n')
|
||||
grubcfg = subprocess.check_output(['find', rootdir, '-name', 'grub.cfg']).decode('utf8').strip().replace(rootdir, '/')
|
||||
subprocess.check_call(['chroot', rootdir, 'grub2-mkconfig', '-o', grubcfg])
|
||||
newroot = None
|
||||
with open('/etc/shadow') as shadowin:
|
||||
shents = shadowin.read().split('\n')
|
||||
for shent in shents:
|
||||
shent = shent.split(':')
|
||||
if not shent:
|
||||
continue
|
||||
if shent[0] == 'root' and shent[1] not in ('*', '!!', ''):
|
||||
newroot = shent[1]
|
||||
if newroot:
|
||||
shlines = None
|
||||
with open(os.path.join(rootdir, 'etc/shadow')) as oshadow:
|
||||
shlines = oshadow.read().split('\n')
|
||||
with open(os.path.join(rootdir, 'etc/shadow'), 'w') as oshadow:
|
||||
for line in shlines:
|
||||
if line.startswith('root:'):
|
||||
line = line.split(':')
|
||||
line[1] = newroot
|
||||
line = ':'.join(line)
|
||||
oshadow.write(line + '\n')
|
||||
partnum = None
|
||||
targblock = None
|
||||
for vol in vols:
|
||||
if vol['mount'] == '/boot/efi':
|
||||
targdev = vol['targetdisk']
|
||||
partnum = re.search('(\d+)$', targdev).group(1)
|
||||
targblock = re.search('(.*)\d+$', targdev).group(1)
|
||||
if targblock:
|
||||
shimpath = subprocess.check_output(['find', os.path.join(rootdir, 'boot/efi'), '-name', 'shimx64.efi']).decode('utf8').strip()
|
||||
shimpath = shimpath.replace(rootdir, '/').replace('/boot/efi', '').replace('//', '/').replace('/', '\\')
|
||||
subprocess.check_call(['efibootmgr', '-c', '-d', targblock, '-l', shimpath, '--part', partnum])
|
||||
#other network interfaces
|
||||
|
||||
|
||||
def had_swap():
|
||||
@ -263,7 +333,7 @@ def install_to_disk(imgpath):
|
||||
progress = 0.99
|
||||
lastprogress = progress
|
||||
progress = progress * 100
|
||||
sys.stdout.write('\rWriting {0}: {1:3.2f}%'.format(vol['mount'], progress).ljust(70))
|
||||
sys.stdout.write('\x1b[1K\rWriting {0}: {1:3.2f}%'.format(vol['mount'], progress))
|
||||
sys.stdout.flush()
|
||||
time.sleep(0.5)
|
||||
stillrunning = copier.poll()
|
||||
@ -284,11 +354,11 @@ def install_to_disk(imgpath):
|
||||
progress = 0.99
|
||||
lastprogress = progress
|
||||
progress = progress * 100
|
||||
sys.stdout.write('\rWriting {0}: {1:3.2f}%'.format(vol['mount'], progress).ljust(70))
|
||||
sys.stdout.write('\x1b[1K\rWriting {0}: {1:3.2f}%'.format(vol['mount'], progress))
|
||||
sys.stdout.flush()
|
||||
time.sleep(0.5)
|
||||
stillrunning = syncrun.poll()
|
||||
sys.stdout.write('\rDone writing {0}'.format(vol['mount']).ljust(70))
|
||||
sys.stdout.write('\x1b[1K\rDone writing {0}'.format(vol['mount']))
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.flush()
|
||||
subprocess.check_call(['umount', '/run/imginst/targ'])
|
||||
|
@ -66,48 +66,59 @@ def sanitize_shadow(shadowfile):
|
||||
newshadow += ':'.join(passent) + '\n'
|
||||
return newshadow
|
||||
|
||||
def mask_file(mdir, filename, maskwith='/run/imgutil/captmp/empty'):
|
||||
if filename.startswith(mdir):
|
||||
filename = filename.replace(mdir, '', 1)
|
||||
if filename[0] == '/':
|
||||
filename = filename[1:]
|
||||
filename = os.path.join(mdir, filename)
|
||||
if filename[0] == '/':
|
||||
filename = filename[1:]
|
||||
filename = os.path.join('/run/imgutil/capin/', filename)
|
||||
if os.path.exists(filename):
|
||||
secontext = os.getxattr(filename, 'security.selinux')
|
||||
_mount_file(maskwith, filename)
|
||||
if secontext:
|
||||
secontext = secontext.split(b'\x00', 1)[0].decode('utf8')
|
||||
subprocess.check_call(['chcon', secontext, maskwith])
|
||||
class FileMasker():
|
||||
def __init__(self, mdir):
|
||||
self.mdir = mdir
|
||||
self.tmpfiles = []
|
||||
|
||||
def __enter__(self):
|
||||
self.tmpfiles = []
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
for tf in self.tmpfiles:
|
||||
os.unlink(tf)
|
||||
|
||||
def mask(self, filename, maskwith=None):
|
||||
mdir = self.mdir
|
||||
if filename.startswith(mdir):
|
||||
filename = filename.replace(mdir, '', 1)
|
||||
if filename[0] == '/':
|
||||
filename = filename[1:]
|
||||
filename = os.path.join(mdir, filename)
|
||||
if filename[0] == '/':
|
||||
filename = filename[1:]
|
||||
filename = os.path.join('/run/imgutil/capin/', filename)
|
||||
for tfilename in glob.glob(filename):
|
||||
secontext = os.getxattr(tfilename, 'security.selinux')
|
||||
if maskwith is None:
|
||||
tmaskwith = tempfile.mkstemp()
|
||||
os.close(tmaskwith[0])
|
||||
tmaskwith = tmaskwith[1]
|
||||
self.tmpfiles.append(tmaskwith)
|
||||
else:
|
||||
tmaskwith = maskwith
|
||||
_mount_file(tmaskwith, tfilename)
|
||||
if secontext:
|
||||
secontext = secontext.split(b'\x00', 1)[0].decode('utf8')
|
||||
subprocess.check_call(['chcon', secontext, tmaskwith])
|
||||
|
||||
def capture_fs(args):
|
||||
fsinfo, fname = args
|
||||
_mount(fsinfo['mount'], '/run/imgutil/capin', flags=MS_BIND|MS_RDONLY)
|
||||
targdir = None
|
||||
mdir = fsinfo['mount']
|
||||
mask_file(mdir, '/etc/shadow', '/run/imgutil/captmp/shadow')
|
||||
mask_file(mdir, '/etc/gshadow', '/run/imgutil/captmp/gshadow')
|
||||
mask_file(mdir, '/etc/fstab', '/run/imgutil/captmp/fstab')
|
||||
mask_file(mdir, '/etc/confluent/confluent.apikey')
|
||||
mask_file(mdir, '/etc/shadow-')
|
||||
mask_file(mdir, '/etc/gshadow-')
|
||||
mask_file(mdir, '/etc/hostname')
|
||||
if '/etc'.startswith(mdir):
|
||||
targdir = '/etc'.replace(mdir, '', 1)
|
||||
targdir = os.path.join('/run/imgutil/capin', targdir)
|
||||
for tname in glob.glob(os.path.join(targdir, 'ssh/*key')):
|
||||
_mount_file('/run/imgutil/captmp/empty', tname)
|
||||
for tname in glob.glob(os.path.join(targdir, 'pki/tls/private/*')):
|
||||
_mount_file('/run/imgutil/captmp/empty', tname)
|
||||
if os.path.exists(os.path.join(targdir, 'sysconfig/network-scripts')):
|
||||
_mount('none', os.path.join(targdir, 'sysconfig/network-scripts'), 'tmpfs')
|
||||
if '/root'.startswith(mdir):
|
||||
targdir = '/root'.replace(mdir, '', 1)
|
||||
for tname in glob.glob(os.path.join(targdir, '.ssh/id_*')):
|
||||
_mount_file('/run/imgutil/captmp/empty, tname')
|
||||
subprocess.check_call(['mksquashfs', '/run/imgutil/capin', fname + '.sfs', '-comp', 'xz'])
|
||||
with FileMasker(mdir) as masker:
|
||||
masker.mask('/etc/shadow', '/run/imgutil/captmp/shadow')
|
||||
masker.mask('/etc/gshadow', '/run/imgutil/captmp/gshadow')
|
||||
masker.mask('/etc/fstab', '/run/imgutil/captmp/fstab')
|
||||
masker.mask('/etc/confluent/confluent.apikey')
|
||||
masker.mask('/etc/shadow-')
|
||||
masker.mask('/etc/gshadow-')
|
||||
masker.mask('/etc/ssh/*key')
|
||||
masker.mask('/etc/pki/tls/private/*')
|
||||
masker.mask('/root/.ssh/id_*')
|
||||
subprocess.check_call(['mksquashfs', '/run/imgutil/capin', fname + '.sfs', '-comp', 'xz'])
|
||||
|
||||
def capture_system():
|
||||
mkdirp('/run/imgutil/capout')
|
||||
|
Loading…
Reference in New Issue
Block a user