Revision b8d4b14a
b/image_creator/os_type/__init__.py | ||
---|---|---|
42 | 42 |
import textwrap |
43 | 43 |
import re |
44 | 44 |
from collections import namedtuple |
45 |
from functools import wraps |
|
45 | 46 |
|
46 | 47 |
|
47 | 48 |
def os_cls(distro, osfamily): |
... | ... | |
67 | 68 |
return wrapper |
68 | 69 |
|
69 | 70 |
|
70 |
def sysprep(enabled=True): |
|
71 |
def sysprep(message, enabled=True):
|
|
71 | 72 |
"""Decorator for system preparation tasks""" |
72 |
def wrapper(func): |
|
73 |
def wrapper1(func):
|
|
73 | 74 |
func.sysprep = True |
74 | 75 |
func.enabled = enabled |
75 | 76 |
func.executed = False |
76 |
return func |
|
77 |
return wrapper |
|
77 |
|
|
78 |
@wraps(func) |
|
79 |
def wrapper2(self, print_message=True): |
|
80 |
if print_message: |
|
81 |
self.out.output(message) |
|
82 |
return func(self) |
|
83 |
|
|
84 |
return wrapper2 |
|
85 |
|
|
86 |
return wrapper1 |
|
78 | 87 |
|
79 | 88 |
|
80 | 89 |
class OSBase(object): |
b/image_creator/os_type/freebsd.py | ||
---|---|---|
43 | 43 |
class Freebsd(Unix): |
44 | 44 |
"""OS class for FreeBSD Unix-like os""" |
45 | 45 |
|
46 |
@sysprep() |
|
47 |
def cleanup_password(self, print_header=True):
|
|
46 |
@sysprep("Cleaning up passwords & locking all user accounts")
|
|
47 |
def cleanup_password(self): |
|
48 | 48 |
"""Remove all passwords and lock all user accounts""" |
49 | 49 |
|
50 |
if print_header: |
|
51 |
self.out.output("Cleaning up passwords & locking all user " |
|
52 |
"accounts") |
|
53 |
|
|
54 | 50 |
master_passwd = [] |
55 | 51 |
|
56 | 52 |
for line in self.g.cat('/etc/master.passwd').splitlines(): |
b/image_creator/os_type/linux.py | ||
---|---|---|
48 | 48 |
self._uuid = dict() |
49 | 49 |
self._persistent = re.compile('/dev/[hsv]d[a-z][1-9]*') |
50 | 50 |
|
51 |
@sysprep(enabled=False) |
|
52 |
def remove_user_accounts(self, print_header=True):
|
|
51 |
@sysprep('Removing user accounts with id greater that 1000', enabled=False)
|
|
52 |
def remove_user_accounts(self): |
|
53 | 53 |
"""Remove all user accounts with id greater than 1000""" |
54 | 54 |
|
55 |
if print_header: |
|
56 |
self.out.output("Removing all user accounts with id greater than " |
|
57 |
"1000") |
|
58 |
|
|
59 | 55 |
if 'USERS' not in self.meta: |
60 | 56 |
return |
61 | 57 |
|
... | ... | |
105 | 101 |
if self.g.is_dir(home) and home.startswith('/home/'): |
106 | 102 |
self.g.rm_rf(home) |
107 | 103 |
|
108 |
@sysprep() |
|
109 |
def cleanup_passwords(self, print_header=True):
|
|
104 |
@sysprep('Cleaning up password & locking all user accounts')
|
|
105 |
def cleanup_passwords(self): |
|
110 | 106 |
"""Remove all passwords and lock all user accounts""" |
111 | 107 |
|
112 |
if print_header: |
|
113 |
self.out.output("Cleaning up passwords & locking all user " |
|
114 |
"accounts") |
|
115 |
|
|
116 | 108 |
shadow = [] |
117 | 109 |
|
118 | 110 |
for line in self.g.cat('/etc/shadow').splitlines(): |
... | ... | |
124 | 116 |
|
125 | 117 |
self.g.write('/etc/shadow', "\n".join(shadow) + '\n') |
126 | 118 |
|
127 |
@sysprep() |
|
128 |
def fix_acpid(self, print_header=True):
|
|
119 |
@sysprep('Fixing acpid powerdown action')
|
|
120 |
def fix_acpid(self): |
|
129 | 121 |
"""Replace acpid powerdown action scripts to immediately shutdown the |
130 | 122 |
system without checking if a GUI is running. |
131 | 123 |
""" |
132 | 124 |
|
133 |
if print_header: |
|
134 |
self.out.output('Fixing acpid powerdown action') |
|
135 |
|
|
136 | 125 |
powerbtn_action = '#!/bin/sh\n\nPATH=/sbin:/bin:/usr/bin\n' \ |
137 | 126 |
'shutdown -h now "Power button pressed"\n' |
138 | 127 |
|
... | ... | |
185 | 174 |
|
186 | 175 |
self.out.warn("No acpi power button event found!") |
187 | 176 |
|
188 |
@sysprep() |
|
189 |
def remove_persistent_net_rules(self, print_header=True):
|
|
177 |
@sysprep('Removing persistent network interface names')
|
|
178 |
def remove_persistent_net_rules(self): |
|
190 | 179 |
"""Remove udev rules that will keep network interface names persistent |
191 | 180 |
after hardware changes and reboots. Those rules will be created again |
192 | 181 |
the next time the image runs. |
193 | 182 |
""" |
194 | 183 |
|
195 |
if print_header: |
|
196 |
self.out.output('Removing persistent network interface names') |
|
197 |
|
|
198 | 184 |
rule_file = '/etc/udev/rules.d/70-persistent-net.rules' |
199 | 185 |
if self.g.is_file(rule_file): |
200 | 186 |
self.g.rm(rule_file) |
201 | 187 |
|
202 |
@sysprep() |
|
203 |
def remove_swap_entry(self, print_header=True):
|
|
188 |
@sysprep('Removing swap entry from fstab')
|
|
189 |
def remove_swap_entry(self): |
|
204 | 190 |
"""Remove swap entry from /etc/fstab. If swap is the last partition |
205 | 191 |
then the partition will be removed when shrinking is performed. If the |
206 | 192 |
swap partition is not the last partition in the disk or if you are not |
207 | 193 |
going to shrink the image you should probably disable this. |
208 | 194 |
""" |
209 | 195 |
|
210 |
if print_header: |
|
211 |
self.out.output('Removing swap entry from fstab') |
|
212 |
|
|
213 | 196 |
new_fstab = "" |
214 | 197 |
fstab = self.g.cat('/etc/fstab') |
215 | 198 |
for line in fstab.splitlines(): |
... | ... | |
222 | 205 |
|
223 | 206 |
self.g.write('/etc/fstab', new_fstab) |
224 | 207 |
|
225 |
@sysprep() |
|
226 |
def use_persistent_block_device_names(self, print_header=True):
|
|
208 |
@sysprep('Replacing fstab & grub non-persistent device references')
|
|
209 |
def use_persistent_block_device_names(self): |
|
227 | 210 |
"""Scan fstab & grub configuration files and replace all non-persistent |
228 | 211 |
device references with UUIDs. |
229 | 212 |
""" |
230 | 213 |
|
231 |
if print_header: |
|
232 |
self.out.output("Replacing fstab & grub non-persistent device " |
|
233 |
"references") |
|
234 |
|
|
235 | 214 |
# convert all devices in fstab to persistent |
236 | 215 |
persistent_root = self._persistent_fstab() |
237 | 216 |
|
b/image_creator/os_type/slackware.py | ||
---|---|---|
40 | 40 |
|
41 | 41 |
class Slackware(Linux): |
42 | 42 |
"""OS class for Slackware Linux""" |
43 |
@sysprep() |
|
44 |
def cleanup_log(self, print_header=True):
|
|
43 |
@sysprep("Emptying all files under /var/log")
|
|
44 |
def cleanup_log(self): |
|
45 | 45 |
"""Empty all files under /var/log""" |
46 | 46 |
|
47 |
if print_header: |
|
48 |
self.out.output('Emptying all files under /var/log') |
|
49 |
|
|
50 | 47 |
# In slackware the metadata about installed packages are |
51 | 48 |
# stored in /var/log/packages. Clearing all /var/log files |
52 | 49 |
# will destroy the package management system. |
b/image_creator/os_type/unix.py | ||
---|---|---|
87 | 87 |
|
88 | 88 |
return True |
89 | 89 |
|
90 |
@sysprep() |
|
91 |
def cleanup_cache(self, print_header=True):
|
|
90 |
@sysprep('Removing files u)nder /var/cache')
|
|
91 |
def cleanup_cache(self): |
|
92 | 92 |
"""Remove all regular files under /var/cache""" |
93 | 93 |
|
94 |
if print_header: |
|
95 |
self.out.output('Removing files under /var/cache') |
|
96 |
|
|
97 | 94 |
self._foreach_file('/var/cache', self.g.rm, ftype='r') |
98 | 95 |
|
99 |
@sysprep() |
|
100 |
def cleanup_tmp(self, print_header=True):
|
|
96 |
@sysprep('Removing files under /tmp and /var/tmp')
|
|
97 |
def cleanup_tmp(self): |
|
101 | 98 |
"""Remove all files under /tmp and /var/tmp""" |
102 | 99 |
|
103 |
if print_header: |
|
104 |
self.out.output('Removing files under /tmp and /var/tmp') |
|
105 |
|
|
106 | 100 |
self._foreach_file('/tmp', self.g.rm_rf, maxdepth=1) |
107 | 101 |
self._foreach_file('/var/tmp', self.g.rm_rf, maxdepth=1) |
108 | 102 |
|
109 |
@sysprep() |
|
110 |
def cleanup_log(self, print_header=True):
|
|
103 |
@sysprep('Emptying all files under /var/log')
|
|
104 |
def cleanup_log(self): |
|
111 | 105 |
"""Empty all files under /var/log""" |
112 | 106 |
|
113 |
if print_header: |
|
114 |
self.out.output('Emptying all files under /var/log') |
|
115 |
|
|
116 | 107 |
self._foreach_file('/var/log', self.g.truncate, ftype='r') |
117 | 108 |
|
118 |
@sysprep(enabled=False) |
|
119 |
def cleanup_mail(self, print_header=True):
|
|
109 |
@sysprep('Removing files under /var/mail & /var/spool/mail', enabled=False)
|
|
110 |
def cleanup_mail(self): |
|
120 | 111 |
"""Remove all files under /var/mail and /var/spool/mail""" |
121 | 112 |
|
122 |
if print_header: |
|
123 |
self.out.output('Removing files under /var/mail & /var/spool/mail') |
|
124 |
|
|
125 | 113 |
if self.g.is_dir('/var/spool/mail'): |
126 | 114 |
self._foreach_file('/var/spool/mail', self.g.rm_rf, maxdepth=1) |
127 | 115 |
|
128 | 116 |
self._foreach_file('/var/mail', self.g.rm_rf, maxdepth=1) |
129 | 117 |
|
130 |
@sysprep() |
|
131 |
def cleanup_userdata(self, print_header=True):
|
|
118 |
@sysprep('Removing sensitive user data')
|
|
119 |
def cleanup_userdata(self): |
|
132 | 120 |
"""Delete sensitive userdata""" |
133 | 121 |
|
134 | 122 |
homedirs = ['/root'] |
135 | 123 |
if self.g.is_dir('/home/'): |
136 | 124 |
homedirs += self._ls('/home/') |
137 | 125 |
|
138 |
if print_header: |
|
139 |
self.out.output("Removing sensitive user data under %s" % |
|
140 |
" ".join(homedirs)) |
|
141 |
|
|
142 | 126 |
for homedir in homedirs: |
143 | 127 |
for data in self.sensitive_userdata: |
144 | 128 |
fname = "%s/%s" % (homedir, data) |
b/image_creator/os_type/windows.py | ||
---|---|---|
65 | 65 |
|
66 | 66 |
return [password] |
67 | 67 |
|
68 |
@sysprep(enabled=True)
|
|
69 |
def disable_ipv6_privacy_extensions(self, print_header=True):
|
|
68 |
@sysprep('Disabling IPv6 privacy extensions')
|
|
69 |
def disable_ipv6_privacy_extensions(self): |
|
70 | 70 |
"""Disable IPv6 privacy extensions""" |
71 | 71 |
|
72 |
if print_header: |
|
73 |
self.out.output("Disabling IPv6 privacy extensions") |
|
74 |
|
|
75 | 72 |
self._guest_exec('netsh interface ipv6 set global ' |
76 | 73 |
'randomizeidentifiers=disabled store=persistent') |
77 | 74 |
|
78 |
@sysprep(enabled=True)
|
|
79 |
def microsoft_sysprep(self, print_header=True):
|
|
75 |
@sysprep('Executing sysprep on the image (may take more that 10 minutes)')
|
|
76 |
def microsoft_sysprep(self): |
|
80 | 77 |
"""Run the Microsoft System Preparation Tool on the Image. This will |
81 | 78 |
remove system-specific data and will make the image ready to be |
82 | 79 |
deployed. After this no other task may run. |
83 | 80 |
""" |
84 | 81 |
|
85 |
if print_header: |
|
86 |
self.out.output("Executing sysprep on the image (may take more " |
|
87 |
"than 10 minutes)") |
|
88 |
|
|
89 | 82 |
self._guest_exec(r'C:\Windows\system32\sysprep\sysprep ' |
90 | 83 |
r'/quiet /generalize /oobe /shutdown') |
91 | 84 |
self.syspreped = True |
Also available in: Unified diff