Statistics
| Branch: | Tag: | Revision:

root / image_creator / os_type / unix.py @ 61d14323

History | View | Annotate | Download (7.1 kB)

1 ae48a082 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
2 ae48a082 Nikos Skalkotos
#
3 ae48a082 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
4 ae48a082 Nikos Skalkotos
# without modification, are permitted provided that the following
5 ae48a082 Nikos Skalkotos
# conditions are met:
6 ae48a082 Nikos Skalkotos
#
7 ae48a082 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
8 ae48a082 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
9 ae48a082 Nikos Skalkotos
#      disclaimer.
10 ae48a082 Nikos Skalkotos
#
11 ae48a082 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
12 ae48a082 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
13 ae48a082 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
14 ae48a082 Nikos Skalkotos
#      provided with the distribution.
15 ae48a082 Nikos Skalkotos
#
16 ae48a082 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 ae48a082 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 ae48a082 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 ae48a082 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 ae48a082 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 ae48a082 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 ae48a082 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 ae48a082 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 ae48a082 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 ae48a082 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 ae48a082 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 ae48a082 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
28 ae48a082 Nikos Skalkotos
#
29 ae48a082 Nikos Skalkotos
# The views and conclusions contained in the software and
30 ae48a082 Nikos Skalkotos
# documentation are those of the authors and should not be
31 ae48a082 Nikos Skalkotos
# interpreted as representing official policies, either expressed
32 ae48a082 Nikos Skalkotos
# or implied, of GRNET S.A.
33 aa2062ba Nikos Skalkotos
34 aa2062ba Nikos Skalkotos
import re
35 aa2062ba Nikos Skalkotos
36 f165adc0 Nikos Skalkotos
from image_creator.os_type import OSBase, sysprep
37 aa2062ba Nikos Skalkotos
38 8c574358 Nikos Skalkotos
39 aa2062ba Nikos Skalkotos
class Unix(OSBase):
40 0d5a999d Nikos Skalkotos
41 f8119e65 Nikos Skalkotos
    sensitive_userdata = [
42 f8119e65 Nikos Skalkotos
        '.bash_history',
43 f8119e65 Nikos Skalkotos
        '.gnupg',
44 e36b5b14 Nikos Skalkotos
        '.ssh',
45 e36b5b14 Nikos Skalkotos
        '.kamakirc',
46 e36b5b14 Nikos Skalkotos
        '.kamaki.history'
47 f8119e65 Nikos Skalkotos
    ]
48 0d5a999d Nikos Skalkotos
49 e77e66a9 Nikos Skalkotos
    def __init__(self, rootdev, ghandler, output):
50 e77e66a9 Nikos Skalkotos
        super(Unix, self).__init__(rootdev, ghandler, output)
51 aa2062ba Nikos Skalkotos
52 5886f568 Nikos Skalkotos
        self.meta["USERS"] = " ".join(self._get_passworded_users())
53 5f7e1e0c Nikos Skalkotos
        # Delete the USERS metadata if empty
54 5f7e1e0c Nikos Skalkotos
        if not len(self.meta['USERS']):
55 5f7e1e0c Nikos Skalkotos
            self.out.warn("No passworded users found!")
56 5f7e1e0c Nikos Skalkotos
            del self.meta['USERS']
57 5f7e1e0c Nikos Skalkotos
58 5886f568 Nikos Skalkotos
    def _get_passworded_users(self):
59 aa2062ba Nikos Skalkotos
        users = []
60 aa2062ba Nikos Skalkotos
        regexp = re.compile('(\S+):((?:!\S+)|(?:[^!*]\S+)|):(?:\S*:){6}')
61 aa2062ba Nikos Skalkotos
62 36e348b6 Nikos Skalkotos
        for line in self.g.cat('/etc/shadow').splitlines():
63 aa2062ba Nikos Skalkotos
            match = regexp.match(line)
64 aa2062ba Nikos Skalkotos
            if not match:
65 aa2062ba Nikos Skalkotos
                continue
66 aa2062ba Nikos Skalkotos
67 aa2062ba Nikos Skalkotos
            user, passwd = match.groups()
68 aa2062ba Nikos Skalkotos
            if len(passwd) > 0 and passwd[0] == '!':
69 564a18ce Nikos Skalkotos
                self.out.warn("Ignoring locked %s account." % user)
70 aa2062ba Nikos Skalkotos
            else:
71 aa2062ba Nikos Skalkotos
                users.append(user)
72 aa2062ba Nikos Skalkotos
73 aa2062ba Nikos Skalkotos
        return users
74 aa2062ba Nikos Skalkotos
75 f165adc0 Nikos Skalkotos
    @sysprep(enabled=False)
76 f165adc0 Nikos Skalkotos
    def remove_user_accounts(self, print_header=True):
77 50273553 Nikos Skalkotos
        """Remove all user accounts with id greater than 1000"""
78 a9c9d939 Nikos Skalkotos
79 a9c9d939 Nikos Skalkotos
        if print_header:
80 f99fe99d Nikos Skalkotos
            self.out.output("Removing all user accounts with id greater than "
81 f99fe99d Nikos Skalkotos
                            "1000")
82 a9c9d939 Nikos Skalkotos
83 5f7e1e0c Nikos Skalkotos
        if 'USERS' not in self.meta:
84 5f7e1e0c Nikos Skalkotos
            return
85 5f7e1e0c Nikos Skalkotos
86 a9c9d939 Nikos Skalkotos
        # Remove users from /etc/passwd
87 a9c9d939 Nikos Skalkotos
        passwd = []
88 a9c9d939 Nikos Skalkotos
        removed_users = {}
89 5886f568 Nikos Skalkotos
        metadata_users = self.meta['USERS'].split()
90 a9c9d939 Nikos Skalkotos
        for line in self.g.cat('/etc/passwd').splitlines():
91 a9c9d939 Nikos Skalkotos
            fields = line.split(':')
92 a9c9d939 Nikos Skalkotos
            if int(fields[2]) > 1000:
93 a9c9d939 Nikos Skalkotos
                removed_users[fields[0]] = fields
94 5886f568 Nikos Skalkotos
                # remove it from the USERS metadata too
95 5886f568 Nikos Skalkotos
                if fields[0] in metadata_users:
96 5886f568 Nikos Skalkotos
                    metadata_users.remove(fields[0])
97 a9c9d939 Nikos Skalkotos
            else:
98 a9c9d939 Nikos Skalkotos
                passwd.append(':'.join(fields))
99 a9c9d939 Nikos Skalkotos
100 5886f568 Nikos Skalkotos
        self.meta['USERS'] = " ".join(metadata_users)
101 5f7e1e0c Nikos Skalkotos
102 5f7e1e0c Nikos Skalkotos
        # Delete the USERS metadata if empty
103 5f7e1e0c Nikos Skalkotos
        if not len(self.meta['USERS']):
104 5f7e1e0c Nikos Skalkotos
            del self.meta['USERS']
105 5f7e1e0c Nikos Skalkotos
106 a9c9d939 Nikos Skalkotos
        self.g.write('/etc/passwd', '\n'.join(passwd) + '\n')
107 a9c9d939 Nikos Skalkotos
108 a9c9d939 Nikos Skalkotos
        # Remove the corresponding /etc/shadow entries
109 a9c9d939 Nikos Skalkotos
        shadow = []
110 a9c9d939 Nikos Skalkotos
        for line in self.g.cat('/etc/shadow').splitlines():
111 a9c9d939 Nikos Skalkotos
            fields = line.split(':')
112 a9c9d939 Nikos Skalkotos
            if fields[0] not in removed_users:
113 a9c9d939 Nikos Skalkotos
                shadow.append(':'.join(fields))
114 a9c9d939 Nikos Skalkotos
115 a9c9d939 Nikos Skalkotos
        self.g.write('/etc/shadow', "\n".join(shadow) + '\n')
116 a9c9d939 Nikos Skalkotos
117 a9c9d939 Nikos Skalkotos
        # Remove the corresponding /etc/group entries
118 a9c9d939 Nikos Skalkotos
        group = []
119 a9c9d939 Nikos Skalkotos
        for line in self.g.cat('/etc/group').splitlines():
120 a9c9d939 Nikos Skalkotos
            fields = line.split(':')
121 a9c9d939 Nikos Skalkotos
            # Remove groups tha have the same name as the removed users
122 a9c9d939 Nikos Skalkotos
            if fields[0] not in removed_users:
123 a9c9d939 Nikos Skalkotos
                group.append(':'.join(fields))
124 a9c9d939 Nikos Skalkotos
125 a9c9d939 Nikos Skalkotos
        self.g.write('/etc/group', '\n'.join(group) + '\n')
126 4cab6d62 Nikos Skalkotos
127 a9c9d939 Nikos Skalkotos
        # Remove home directories
128 a9c9d939 Nikos Skalkotos
        for home in [field[5] for field in removed_users.values()]:
129 a9c9d939 Nikos Skalkotos
            if self.g.is_dir(home) and home.startswith('/home/'):
130 a9c9d939 Nikos Skalkotos
                self.g.rm_rf(home)
131 a9c9d939 Nikos Skalkotos
132 f165adc0 Nikos Skalkotos
    @sysprep()
133 f165adc0 Nikos Skalkotos
    def cleanup_passwords(self, print_header=True):
134 51fab9c9 Nikos Skalkotos
        """Remove all passwords and lock all user accounts"""
135 51fab9c9 Nikos Skalkotos
136 51fab9c9 Nikos Skalkotos
        if print_header:
137 f99fe99d Nikos Skalkotos
            self.out.output("Cleaning up passwords & locking all user "
138 f99fe99d Nikos Skalkotos
                            "accounts")
139 51fab9c9 Nikos Skalkotos
140 51fab9c9 Nikos Skalkotos
        shadow = []
141 51fab9c9 Nikos Skalkotos
142 51fab9c9 Nikos Skalkotos
        for line in self.g.cat('/etc/shadow').splitlines():
143 51fab9c9 Nikos Skalkotos
            fields = line.split(':')
144 51fab9c9 Nikos Skalkotos
            if fields[1] not in ('*', '!'):
145 51fab9c9 Nikos Skalkotos
                fields[1] = '!'
146 51fab9c9 Nikos Skalkotos
147 51fab9c9 Nikos Skalkotos
            shadow.append(":".join(fields))
148 51fab9c9 Nikos Skalkotos
149 a9c9d939 Nikos Skalkotos
        self.g.write('/etc/shadow', "\n".join(shadow) + '\n')
150 51fab9c9 Nikos Skalkotos
151 f165adc0 Nikos Skalkotos
    @sysprep()
152 f165adc0 Nikos Skalkotos
    def cleanup_cache(self, print_header=True):
153 f8119e65 Nikos Skalkotos
        """Remove all regular files under /var/cache"""
154 22a6d232 Nikos Skalkotos
155 3f70f242 Nikos Skalkotos
        if print_header:
156 e77e66a9 Nikos Skalkotos
            self.out.output('Removing files under /var/cache')
157 22a6d232 Nikos Skalkotos
158 c16922f7 Nikos Skalkotos
        self.foreach_file('/var/cache', self.g.rm, ftype='r')
159 0d5a999d Nikos Skalkotos
160 f165adc0 Nikos Skalkotos
    @sysprep()
161 f165adc0 Nikos Skalkotos
    def cleanup_tmp(self, print_header=True):
162 f8119e65 Nikos Skalkotos
        """Remove all files under /tmp and /var/tmp"""
163 22a6d232 Nikos Skalkotos
164 3f70f242 Nikos Skalkotos
        if print_header:
165 e77e66a9 Nikos Skalkotos
            self.out.output('Removing files under /tmp and /var/tmp')
166 22a6d232 Nikos Skalkotos
167 8c574358 Nikos Skalkotos
        self.foreach_file('/tmp', self.g.rm_rf, maxdepth=1)
168 9297c398 Nikos Skalkotos
        self.foreach_file('/var/tmp', self.g.rm_rf, maxdepth=1)
169 0d5a999d Nikos Skalkotos
170 f165adc0 Nikos Skalkotos
    @sysprep()
171 f165adc0 Nikos Skalkotos
    def cleanup_log(self, print_header=True):
172 f8119e65 Nikos Skalkotos
        """Empty all files under /var/log"""
173 22a6d232 Nikos Skalkotos
174 3f70f242 Nikos Skalkotos
        if print_header:
175 e77e66a9 Nikos Skalkotos
            self.out.output('Emptying all files under /var/log')
176 22a6d232 Nikos Skalkotos
177 8c574358 Nikos Skalkotos
        self.foreach_file('/var/log', self.g.truncate, ftype='r')
178 0d5a999d Nikos Skalkotos
179 f165adc0 Nikos Skalkotos
    @sysprep(enabled=False)
180 f165adc0 Nikos Skalkotos
    def cleanup_mail(self, print_header=True):
181 f8119e65 Nikos Skalkotos
        """Remove all files under /var/mail and /var/spool/mail"""
182 22a6d232 Nikos Skalkotos
183 3f70f242 Nikos Skalkotos
        if print_header:
184 e77e66a9 Nikos Skalkotos
            self.out.output('Removing files under /var/mail & /var/spool/mail')
185 22a6d232 Nikos Skalkotos
186 f8119e65 Nikos Skalkotos
        self.foreach_file('/var/spool/mail', self.g.rm_rf, maxdepth=1)
187 f8119e65 Nikos Skalkotos
        self.foreach_file('/var/mail', self.g.rm_rf, maxdepth=1)
188 9297c398 Nikos Skalkotos
189 f165adc0 Nikos Skalkotos
    @sysprep()
190 f165adc0 Nikos Skalkotos
    def cleanup_userdata(self, print_header=True):
191 f8119e65 Nikos Skalkotos
        """Delete sensitive userdata"""
192 22a6d232 Nikos Skalkotos
193 0d5a999d Nikos Skalkotos
        homedirs = ['/root'] + self.ls('/home/')
194 0d5a999d Nikos Skalkotos
195 3f70f242 Nikos Skalkotos
        if print_header:
196 f99fe99d Nikos Skalkotos
            self.out.output("Removing sensitive user data under %s" %
197 f99fe99d Nikos Skalkotos
                            " ".join(homedirs))
198 3f70f242 Nikos Skalkotos
199 0d5a999d Nikos Skalkotos
        for homedir in homedirs:
200 0d5a999d Nikos Skalkotos
            for data in self.sensitive_userdata:
201 0d5a999d Nikos Skalkotos
                fname = "%s/%s" % (homedir, data)
202 0d5a999d Nikos Skalkotos
                if self.g.is_file(fname):
203 0d5a999d Nikos Skalkotos
                    self.g.scrub_file(fname)
204 e1e7b843 Nikos Skalkotos
                elif self.g.is_dir(fname):
205 e1e7b843 Nikos Skalkotos
                    self.foreach_file(fname, self.g.scrub_file, ftype='r')
206 aa2062ba Nikos Skalkotos
207 aa2062ba Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :