| Summary: | Firstboot root user password and configure network gui. | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Kim <kim> |
| Component: | firstboot | Assignee: | Martin Gracik <mgracik> |
| Status: | CLOSED WONTFIX | QA Contact: | Fedora Extras Quality Assurance <extras-qa> |
| Severity: | low | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | rawhide | CC: | bcl, dmach, mgracik |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | Bug Fix | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2011-09-12 10:50:24 UTC | Type: | --- |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
Code submissions need to be worked upstream first. In the case of firstboot, that would be in the Fedora project. Reassigning. Kim, what is the reason for these modules? They were removed from firstboot in the past. The end user may not be installing the software onto the box, but receiving a box pre-installed. In this case we would like the user to be able to set the root password of the box and the network configuration when the box first boots. I did notice that between centos 5 and centos 6 that the design of firstboot changed. I would suggest that perhaps because the design of firstboot seems to have changed between the two, that the old modules were dropped because no one ported them over to the new structure. So you want this for RHEL6, right? The rootpassword module was added to RHEL6.1, I think. If you use reconfig mode for firstboot, you will get the rootpassword module. The network module was dropped, because it didn't provide any real functionality, just a button which when clicked run system-config-network. So it was thought redundant, because if you want to change the network settings, you can run system-config-network from the running system. There is a users module, however, sometimes it would be helpful to only present a root user password change. The users screen allows the user to create and modify a large number of users at once. I would think that you would want to finish the configuration option at boot time, so although it may be considered redundant, it might be helpful to have it set at boot time instead of requiring the user to login to the box after firstboot. I simply provided the code above as it may be helpful to others, as I wanted to contribute back to a project I'm using. The odd thing is in non-graphic mode there is still an option to configure the network, but not an option for users. It seems that firstboot is inconsistent in its feature set. In firstboot-1.110.10-1 there is a separate root password module, but it only appears if you run firstboot in reconfig mode. You can enable the reconfig mode during the first boot time, before you login. There's no firstboot in text mode anymore. What you see is /usr/bin/setup, that's a different application. I do not influence what modules are there. I was looking in firstboot-1.110.8-1, which didn't appear to have a rootpassword.py module; so thanks for letting me know. I think it is unfortunate that there is a disconnect between firstboot and /usr/bin/setup, since they provide the same functionality, but one is text mode while the other is graphics mode. I would highly recommend getting with the person that supports /usr/bin/setup and implementing the same functionality in both applications. Thanks you for taking the time to read and understand my suggestions! We rely on more and more GUI tools in firstboot such as system-config-network, system-config-user etc. That's why some modules are not available in text mode. I'm not going to provide the root password module in firstboot for fedora. You can create a normal user and change root password with sudo. Or you can change root password in the Advanced settings window on the create user screen. I also hope that in the near future Fedora will work with root user disabled, so I don't see a point in reintroducing the rootpassword module again, when it was removed some time ago for some reason. As for the configure network module. You can use system-config-network. Again, we had it, it was removed, because it was seen as unnecessary, so I don't see a reason to put it back, because it has no added value to the system-config-network utility. |
Description of problem: I've written a set root password module and a networking module for the GUI for firstboot. Here is the patch. This does not include the needed modifications to the spec file. The firstboot.te is for the network configuration gui. It needs to be build and installed for SELinux compatibility. This also includes a fix that allows a user when in a popup window to be able to click on the background and not be able to regain focus on the popup window. diff -uNr firstboot-1.110.8/firstboot/interface.py firstboot-1.110.8-diff/firstboot/interface.py --- firstboot-1.110.8/firstboot/interface.py 2011-07-08 08:34:49.429178847 -0600 +++ firstboot-1.110.8-diff/firstboot/interface.py 2011-07-08 08:34:43.138178850 -0600 @@ -196,6 +196,7 @@ """ # Create the initial window and a vbox to fill it with. self.win = gtk.Window() + self.win.set_keep_below(True) self.win.set_position(gtk.WIN_POS_CENTER) self.win.set_decorated(False) # we don't set border width here so that the sidebar will meet diff -uNr firstboot-1.110.8/firstboot.te firstboot-1.110.8-diff/firstboot.te --- firstboot-1.110.8/firstboot.te 1969-12-31 17:00:00.000000000 -0700 +++ firstboot-1.110.8-diff/firstboot.te 2011-07-08 08:34:43.142178850 -0600 @@ -0,0 +1,13 @@ + +module firstboot 1.0; + +require { + type firstboot_t; + type NetworkManager_t; + class dbus send_msg; +} + +#============= NetworkManager_t ============== +#!!!! This avc is allowed in the current policy + +allow NetworkManager_t firstboot_t:dbus send_msg; diff -uNr firstboot-1.110.8/modules/network.py firstboot-1.110.8-diff/modules/network.py --- firstboot-1.110.8/modules/network.py 1969-12-31 17:00:00.000000000 -0700 +++ firstboot-1.110.8-diff/modules/network.py 2011-07-08 08:34:43.095178850 -0600 @@ -0,0 +1,252 @@ +# +# Kim Ebert <kim.ebert> +# Chris Lumens <clumens> +# +# Copyright 2008 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties 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, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +import gtk +import libuser +import os, re, string, sys, time +import os.path +import subprocess + +from firstboot.config import * +from firstboot.constants import * +from firstboot.functions import * +from firstboot.module import * + +import gettext +_ = lambda x: gettext.ldgettext("firstboot", x) +N_ = lambda x: x + +sys.path.append("/usr/share/system-config-users") +import userGroupCheck + +class moduleClass(Module): + def __init__(self): + Module.__init__(self) + self.priority = 100 + self.sidebarTitle = N_("Network Settings") + self.title = N_("Network Settings") + self.icon = "create-user.png" + + self.admin = libuser.admin() + self.nisFlag = None + + self._problemFiles = [] + + self._count = 0 + + def _chown(self, arg, dirname, names): + for n in names: + try: + os.lchown("%s/%s" % (dirname, n), arg[0], arg[1]) + + # Update the UI from time to time, but not so often as to + # really slow down the chown. + self._count += 1 + if self._count % 100 == 0: + while gtk.events_pending(): + gtk.main_iteration(False) + except: + self._problemFiles.append("%s/%s" % (dirname, n)) + + + def _sanityCheckHostname(self,hostname): + if len(hostname) < 1: + return None + + if len(hostname) > 255: + return _("Hostname must be 255 or fewer characters in length.") + + validStart = string.ascii_letters + string.digits + validAll = validStart + ".-" + + if string.find(validStart, hostname[0]) == -1: + return _("Hostname must start with a valid character in the ranges " + "'a-z', 'A-Z', or '0-9'") + + for i in range(1, len(hostname)): + if string.find(validAll, hostname[i]) == -1: + return _("Hostnames can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.'") + + return None + + + def apply(self, interface, testing=False): + if testing: + return RESULT_SUCCESS + + hostname = string.strip(self.hostEntry.get_text()) + + herrors = self._sanityCheckHostname(hostname) + + if not hostname: + self._showErrorMessage( _("You must enter a valid hostname for this " + "computer.") ) + return RESULT_FAILURE + + if (herrors is not None): + self._showErrorMessage( _("The hostname \"%(hostname)s\" is not " + "valid for the following reason:\n\n" + "%(herrors)s") + % {'hostname': hostname, + 'herrors': herrors}) + return RESULT_FAILURE + + + try: + cmd = ["/bin/sed", "-i", "-e" ,"s/HOSTNAME=.*/HOSTNAME=" + re.escape(hostname) + "/g", "/etc/sysconfig/network"] + subprocess.Popen(cmd).wait() + cmd = ["/bin/sed", "-n", "-e" ,"s/HOSTNAME=\(.*\)/\\1/p", "/etc/sysconfig/network"] + hostname_new = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.readline() + hostname_new = string.strip(hostname_new) + + if (hostname != hostname_new): + raise Exception("Unable to set hostname") + except: + self._showErrorMessage( _("Unable to set hostname!") ) + + #restart the network to make the network settings effective + try: + cmd = ["/etc/init.d/network restart"] + subprocess.Popen(cmd, shell=True).wait() + except: + pass + + return RESULT_SUCCESS + + def createScreen(self): + self.vbox = gtk.VBox(spacing=10) + + label = gtk.Label(_("Type the network name for the Linux server, then " + "click <b>Network Manager</b> to configure a static " + "IP address for this computer.")) + + label.set_use_markup(True) + label.set_line_wrap(True) + label.set_alignment(0.0, 0.5) + label.set_size_request(500, -1) + + hostname = None + + try: + cmd = ["/bin/sed", "-n", "-e" ,"s/HOSTNAME=\(.*\)/\\1/p", "/etc/sysconfig/network"] + hostname = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.readline() + hostname = string.strip(hostname) + except Exception as e: + print e + + if (hostname == None or hostname == ""): + hostname = "localhost.localdomain" + + self.hostEntry = gtk.Entry() + self.hostEntry.set_text(hostname) + + self.vbox.pack_start(label, False, True) + + table = gtk.Table(2, 4) + table.set_row_spacings(6) + table.set_col_spacings(6) + + label = gtk.Label(_("_Hostname:")) + label.set_use_underline(True) + label.set_mnemonic_widget(self.hostEntry) + label.set_alignment(0.0, 0.5) + table.attach(label, 0, 1, 2, 3, gtk.FILL) + table.attach(self.hostEntry, 1, 2, 2, 3, gtk.SHRINK, gtk.FILL, 5) + + self.vbox.pack_start(table, False) + + nwceHBox = gtk.HBox() + nwceButton = gtk.Button(_("_Network Manager")) + nwceButton.connect("clicked", self._runNWCE) + align = gtk.Alignment() + align.add(nwceButton) + align.set(0.0, 0.5, 0.0, 1.0) + nwceHBox.pack_start(align, True) + self.vbox.pack_start(nwceHBox, False, False) + + def focus(self): + self.hostEntry.grab_focus() + + def initializeUI(self): + pass + + def _runAuthconfig(self, *args): + self.nisFlag = 1 + + # Create a gtkInvisible to block until authconfig is done. + i = gtk.Invisible() + i.grab_add() + + pid = start_process("/usr/bin/authconfig-gtk", "--firstboot") + + while True: + while gtk.events_pending(): + gtk.main_iteration_do() + + child_pid, status = os.waitpid(pid, os.WNOHANG) + if child_pid == pid: + break + else: + time.sleep(0.1) + + i.grab_remove() + + def _waitWindow(self, text): + # Shamelessly copied from gui.py in anaconda. + win = gtk.Window() + win.set_title(_("Please wait")) + win.set_position(gtk.WIN_POS_CENTER) + + label = gtk.Label(text) + + box = gtk.Frame() + box.set_border_width(10) + box.add(label) + box.set_shadow_type(gtk.SHADOW_NONE) + + win.add(box) + win.set_default_size(-1, -1) + return win + + def _showErrorMessage(self, text): + dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, text) + dlg.set_position(gtk.WIN_POS_CENTER) + dlg.set_modal(True) + rc = dlg.run() + dlg.destroy() + return None + + def _runNWCE(self, *args): + i = gtk.Invisible() + i.grab_add() + + pid = start_process("/usr/bin/nm-connection-editor") + + while True: + while gtk.events_pending(): + gtk.main_iteration_do() + + child_pid, status = os.waitpid(pid, os.WNOHANG) + if child_pid == pid: + break + else: + time.sleep(0.1) + + i.grab_remove () diff -uNr firstboot-1.110.8/modules/rootpassword.py firstboot-1.110.8-diff/modules/rootpassword.py --- firstboot-1.110.8/modules/rootpassword.py 1969-12-31 17:00:00.000000000 -0700 +++ firstboot-1.110.8-diff/modules/rootpassword.py 2011-07-08 08:34:43.092178850 -0600 @@ -0,0 +1,212 @@ +# +# Kim Ebert <kim.ebert> +# Chris Lumens <clumens> +# +# Copyright 2008 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties 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, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +import gtk +import libuser +import os, string, sys, time +import os.path + +from firstboot.config import * +from firstboot.constants import * +from firstboot.functions import * +from firstboot.module import * + +import gettext +_ = lambda x: gettext.ldgettext("firstboot", x) +N_ = lambda x: x + +sys.path.append("/usr/share/system-config-users") +import userGroupCheck + +class moduleClass(Module): + def __init__(self): + Module.__init__(self) + self.priority = 100 + self.sidebarTitle = N_("Root Password") + self.title = N_("Root Password") + self.icon = "create-user.png" + + self.admin = libuser.admin() + self.nisFlag = None + + self._problemFiles = [] + + self._count = 0 + + def _chown(self, arg, dirname, names): + for n in names: + try: + os.lchown("%s/%s" % (dirname, n), arg[0], arg[1]) + + # Update the UI from time to time, but not so often as to + # really slow down the chown. + self._count += 1 + if self._count % 100 == 0: + while gtk.events_pending(): + gtk.main_iteration(False) + except: + self._problemFiles.append("%s/%s" % (dirname, n)) + + def apply(self, interface, testing=False): + if testing: + return RESULT_SUCCESS + + username = string.strip("root") + + if username == "" and self.nisFlag: + # If they've run authconfig, don't pop up messageDialog + return RESULT_SUCCESS + + password = self.passwordEntry.get_text() + confirm = self.confirmEntry.get_text() + + if not password or not confirm: + self._showErrorMessage(_("You must enter and confirm a password for this user.")) + self.passwordEntry.set_text("") + self.confirmEntry.set_text("") + self.passwordEntry.grab_focus() + return RESULT_FAILURE + + if password != confirm: + self._showErrorMessage(_("The passwords do not match. Please enter " + "the password again.")) + self.passwordEntry.set_text("") + self.confirmEntry.set_text("") + self.passwordEntry.grab_focus() + return RESULT_FAILURE + elif not userGroupCheck.isPasswordOk(password, self.passwordEntry): + return RESULT_FAILURE + + user = self.admin.lookupUserByName(username) + + userEnt = user + + self.admin.setpassUser(userEnt, self.passwordEntry.get_text(), 0) + + return RESULT_SUCCESS + + def createScreen(self): + self.vbox = gtk.VBox(spacing=10) + + label = gtk.Label(_("Use this screen to set the password for the root user " + "on the Linux machine. This user is disabled for ssh access. ")) + + label.set_line_wrap(True) + label.set_alignment(0.0, 0.5) + label.set_size_request(500, -1) + + self.passwordEntry = gtk.Entry() + self.passwordEntry.set_visibility(False) + self.confirmEntry = gtk.Entry() + self.confirmEntry.set_visibility(False) + + self.vbox.pack_start(label, False, True) + + table = gtk.Table(2, 4) + table.set_row_spacings(6) + table.set_col_spacings(6) + + label = gtk.Label(_("_Password:")) + label.set_use_underline(True) + label.set_mnemonic_widget(self.passwordEntry) + label.set_alignment(0.0, 0.5) + table.attach(label, 0, 1, 2, 3, gtk.FILL) + table.attach(self.passwordEntry, 1, 2, 2, 3, gtk.SHRINK, gtk.FILL, 5) + + label = gtk.Label(_("Confir_m Password:")) + label.set_use_underline(True) + label.set_mnemonic_widget(self.confirmEntry) + label.set_alignment(0.0, 0.5) + table.attach(label, 0, 1, 3, 4, gtk.FILL) + table.attach(self.confirmEntry, 1, 2, 3, 4, gtk.SHRINK, gtk.FILL, 5) + + self.vbox.pack_start(table, False) + + print self.vbox + + def focus(self): + self.passwordEntry.grab_focus() + + def initializeUI(self): + pass + + def _runAuthconfig(self, *args): + self.nisFlag = 1 + + # Create a gtkInvisible to block until authconfig is done. + i = gtk.Invisible() + i.grab_add() + + pid = start_process("/usr/bin/authconfig-gtk", "--firstboot") + + while True: + while gtk.events_pending(): + gtk.main_iteration_do() + + child_pid, status = os.waitpid(pid, os.WNOHANG) + if child_pid == pid: + break + else: + time.sleep(0.1) + + i.grab_remove() + + def _waitWindow(self, text): + # Shamelessly copied from gui.py in anaconda. + win = gtk.Window() + win.set_title(_("Please wait")) + win.set_position(gtk.WIN_POS_CENTER) + + label = gtk.Label(text) + + box = gtk.Frame() + box.set_border_width(10) + box.add(label) + box.set_shadow_type(gtk.SHADOW_NONE) + + win.add(box) + win.set_default_size(-1, -1) + return win + + def _showErrorMessage(self, text): + dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, text) + dlg.set_position(gtk.WIN_POS_CENTER) + dlg.set_modal(True) + rc = dlg.run() + dlg.destroy() + return None + + def _runSCU(self, *args): + i = gtk.Invisible() + i.grab_add() + + pid = start_process("/usr/bin/system-config-users") + + while True: + while gtk.events_pending(): + gtk.main_iteration_do() + + child_pid, status = os.waitpid(pid, os.WNOHANG) + if child_pid == pid: + break + else: + time.sleep(0.1) + + i.grab_remove () Version-Release number of selected component (if applicable): How reproducible: Steps to Reproduce: 1. 2. 3. Actual results: Expected results: Additional info: