From 293a6fbe1dea6a77b1394ced5399105a7e5181a8 Mon Sep 17 00:00:00 2001 From: Nikos Skalkotos <skalkoto@grnet.gr> Date: Mon, 15 Dec 2014 19:04:47 +0200 Subject: [PATCH] Add initial support for OpenBSD * Split code from freebsd.py to bsd.py * Make {Open,Net,Free}bsd classes inherit from Bsd --- image_creator/os_type/bsd.py | 142 +++++++++++++++++++++++++++++++ image_creator/os_type/freebsd.py | 66 ++------------ image_creator/os_type/netbsd.py | 4 +- image_creator/os_type/openbsd.py | 27 ++++++ 4 files changed, 176 insertions(+), 63 deletions(-) create mode 100644 image_creator/os_type/bsd.py create mode 100644 image_creator/os_type/openbsd.py diff --git a/image_creator/os_type/bsd.py b/image_creator/os_type/bsd.py new file mode 100644 index 0000000..510818b --- /dev/null +++ b/image_creator/os_type/bsd.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2011-2014 GRNET S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""This module hosts OS-specific code for *BSD.""" + +from image_creator.os_type.unix import Unix, sysprep + +import re + + +class Bsd(Unix): + """OS class for *BSD Unix-like operating system""" + + @sysprep("Cleaning up passwords & locking all user accounts") + def _cleanup_password(self): + """Remove all passwords and lock all user accounts""" + + master_passwd = [] + + for line in self.image.g.cat('/etc/master.passwd').splitlines(): + + # Check for empty or comment lines + if len(line.split('#')[0]) == 0: + master_passwd.append(line) + continue + + fields = line.split(':') + if fields[1] not in ('*', '!'): + fields[1] = '!' + + master_passwd.append(":".join(fields)) + + self.image.g.write( + '/etc/master.passwd', "\n".join(master_passwd) + '\n') + + # Make sure no one can login on the system + self.image.g.rm_rf('/etc/spwd.db') + + def _check_enabled_sshd(self): + """Check if the ssh daemon is enabled at boot""" + return False + + def _do_collect_metadata(self): + """Collect metadata about the OS""" + super(Bsd, self)._do_collect_metadata() + + users = self._get_passworded_users() + + self.meta["USERS"] = " ".join(users) + + # The original product name key is long and ugly + self.meta['DESCRIPTION'] = \ + self.meta['DESCRIPTION'].split('#')[0].strip() + + # Delete the USERS metadata if empty + if not len(self.meta['USERS']): + self.out.warn("No passworded users found!") + del self.meta['USERS'] + + # Check if ssh is enabled + sshd_enabled = self._check_enabled_sshd() + + if sshd_enabled: + ssh = [] + opts = self.ssh_connection_options(users) + for user in opts['users']: + ssh.append("ssh:port=%d,user=%s" % (opts['port'], user)) + + if 'REMOTE_CONNECTION' not in self.meta: + self.meta['REMOTE_CONNECTION'] = "" + else: + self.meta['REMOTE_CONNECTION'] += " " + + if len(users): + self.meta['REMOTE_CONNECTION'] += " ".join(ssh) + else: + self.meta['REMOTE_CONNECTION'] += "ssh:port=%d" % opts['port'] + else: + self.out.warn("OpenSSH Daemon is not configured to run on boot") + + def _get_passworded_users(self): + """Returns a list of non-locked user accounts""" + users = [] + regexp = re.compile( + '^([^:]+):((?:![^:]+)|(?:[^!*][^:]+)|):(?:[^:]*:){7}(?:[^:]*)' + ) + + for line in self.image.g.cat('/etc/master.passwd').splitlines(): + line = line.split('#')[0] + match = regexp.match(line) + if not match: + continue + + user, passwd = match.groups() + if len(passwd) > 0 and passwd[0] == '!': + self.out.warn("Ignoring locked %s account." % user) + else: + # Put root in the beginning. + if user == 'root': + users.insert(0, user) + else: + users.append(user) + + return users + + def _do_mount(self, readonly): + """Mount partitions in the correct order""" + + critical_mpoints = ('/', '/etc', '/root', '/home', '/var') + + mopts1 = "ufstype=44bsd,%s" % ('ro' if readonly else 'rw') + mopts2 = "ufstype=ufs2,%s" % ('ro' if readonly else 'rw') + for mp, dev in self._mountpoints(): + try: + try: + self.image.g.mount_vfs(mopts2, 'ufs', dev, mp) + except RuntimeError: + self.image.g.mount_vfs(mopts1, 'ufs', dev, mp) + except RuntimeError as msg: + if mp in critical_mpoints: + self._mount_error = str(msg) + return False + else: + self._mount_warnings.append('%s (ignored)' % msg) + + return True + +# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : diff --git a/image_creator/os_type/freebsd.py b/image_creator/os_type/freebsd.py index bacd0aa..2ec89e8 100644 --- a/image_creator/os_type/freebsd.py +++ b/image_creator/os_type/freebsd.py @@ -17,12 +17,12 @@ """This module hosts OS-specific code for FreeBSD.""" -from image_creator.os_type.unix import Unix, sysprep +from image_creator.os_type.bsd import Bsd, sysprep import re -class Freebsd(Unix): +class Freebsd(Bsd): """OS class for FreeBSD Unix-like operating system""" @sysprep("Cleaning up passwords & locking all user accounts") @@ -50,24 +50,9 @@ class Freebsd(Unix): # Make sure no one can login on the system self.image.g.rm_rf('/etc/spwd.db') - def _do_collect_metadata(self): - """Collect metadata about the OS""" - super(Freebsd, self)._do_collect_metadata() + def _check_enabled_sshd(self): + """Check if the sshd is enabled at boot""" - users = self._get_passworded_users() - - self.meta["USERS"] = " ".join(users) - - # The original product name key is long and ugly - self.meta['DESCRIPTION'] = \ - self.meta['DESCRIPTION'].split('#')[0].strip() - - # Delete the USERS metadata if empty - if not len(self.meta['USERS']): - self.out.warn("No passworded users found!") - del self.meta['USERS'] - - # Check if ssh is enabled sshd_enabled = False sshd_service = re.compile(r'^sshd_enable=.+$') @@ -87,23 +72,7 @@ class Freebsd(Unix): if sshd_service.match(line): sshd_enabled = sshd_yes.match(line) is not None - if sshd_enabled: - ssh = [] - opts = self.ssh_connection_options(users) - for user in opts['users']: - ssh.append("ssh:port=%d,user=%s" % (opts['port'], user)) - - if 'REMOTE_CONNECTION' not in self.meta: - self.meta['REMOTE_CONNECTION'] = "" - else: - self.meta['REMOTE_CONNECTION'] += " " - - if len(users): - self.meta['REMOTE_CONNECTION'] += " ".join(ssh) - else: - self.meta['REMOTE_CONNECTION'] += "ssh:port=%d" % opts['port'] - else: - self.out.warn("OpenSSH Daemon is not configured to run on boot") + return sshd_enabled def _do_inspect(self): """Run various diagnostics to check if media is supported""" @@ -117,31 +86,6 @@ class Freebsd(Unix): else: self.out.success(ptype) - def _get_passworded_users(self): - """Returns a list of non-locked user accounts""" - users = [] - regexp = re.compile( - '^([^:]+):((?:![^:]+)|(?:[^!*][^:]+)|):(?:[^:]*:){7}(?:[^:]*)' - ) - - for line in self.image.g.cat('/etc/master.passwd').splitlines(): - line = line.split('#')[0] - match = regexp.match(line) - if not match: - continue - - user, passwd = match.groups() - if len(passwd) > 0 and passwd[0] == '!': - self.out.warn("Ignoring locked %s account." % user) - else: - # Put root in the beginning. - if user == 'root': - users.insert(0, user) - else: - users.append(user) - - return users - def _do_mount(self, readonly): """Mount partitions in the correct order""" diff --git a/image_creator/os_type/netbsd.py b/image_creator/os_type/netbsd.py index 002c5c8..e52b65a 100644 --- a/image_creator/os_type/netbsd.py +++ b/image_creator/os_type/netbsd.py @@ -17,10 +17,10 @@ """This module hosts OS-specific code for NetBSD.""" -from image_creator.os_type.unix import Unix +from image_creator.os_type.bsd import Bsd -class Netbsd(Unix): +class Netbsd(Bsd): """OS class for NetBSD""" pass diff --git a/image_creator/os_type/openbsd.py b/image_creator/os_type/openbsd.py new file mode 100644 index 0000000..0a916f7 --- /dev/null +++ b/image_creator/os_type/openbsd.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2011-2014 GRNET S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""This module hosts OS-specific code for OpenBSD.""" + +from image_creator.os_type.bsd import Bsd + + +class Openbsd(Bsd): + """OS class for OpenBSD""" + pass + +# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : -- GitLab