diff options
-rwxr-xr-x | setup.py | 5 | ||||
-rw-r--r-- | src/virtBootstrap/utils.py | 33 | ||||
-rwxr-xr-x | src/virtBootstrap/virt_bootstrap.py | 18 |
3 files changed, 41 insertions, 15 deletions
@@ -112,6 +112,11 @@ setup( cmdclass={ 'pylint': CheckPylint }, + + # virt-bootstrap uses passlib to compute the hash of + # root password for root file system. + install_requires=['passlib>=1.6.1'], + extras_require={ 'dev': [ 'pylint', diff --git a/src/virtBootstrap/utils.py b/src/virtBootstrap/utils.py index a65d3f5..e1e681c 100644 --- a/src/virtBootstrap/utils.py +++ b/src/virtBootstrap/utils.py @@ -32,6 +32,7 @@ import tempfile import logging from subprocess import CalledProcessError, PIPE, Popen +import passlib.hosts # pylint: disable=invalid-name # Create logger @@ -331,6 +332,38 @@ def str2float(element): return None +def set_root_password(rootfs, password): + """ + Set password on the root user within root filesystem + """ + shadow_file = os.path.join(rootfs, "etc/shadow") + + shadow_file_permissions = os.stat(shadow_file)[0] + # Set read-write permissions to shadow file + # 438 = 0110110110 = -rw-rw-rw- + os.chmod(shadow_file, 438) + try: + with open(shadow_file) as orig_file: + shadow_content = orig_file.read().split('\n') + + for index, line in enumerate(shadow_content): + if line.startswith('root'): + line_split = line.split(':') + line_split[1] = passlib.hosts.linux_context.hash(password) + shadow_content[index] = ':'.join(line_split) + break + + with open(shadow_file, "w") as new_file: + new_file.write('\n'.join(shadow_content)) + + except Exception: + raise + + finally: + # Restore original permissions + os.chmod(shadow_file, shadow_file_permissions) + + def write_progress(prog): """ Write progress output to console diff --git a/src/virtBootstrap/virt_bootstrap.py b/src/virtBootstrap/virt_bootstrap.py index c66cc92..b43c87e 100755 --- a/src/virtBootstrap/virt_bootstrap.py +++ b/src/virtBootstrap/virt_bootstrap.py @@ -27,7 +27,6 @@ import logging import sys import os from textwrap import dedent -from subprocess import CalledProcessError, Popen, PIPE try: from urlparse import urlparse except ImportError: @@ -70,18 +69,6 @@ def get_source(source_type): raise Exception("Invalid image URL scheme: '%s'" % source_type) -def set_root_password(rootfs, password): - """ - Set password on the root user in rootfs - """ - users = 'root:%s' % password - args = ['chpasswd', '-R', rootfs] - chpasswd = Popen(args, stdin=PIPE) - chpasswd.communicate(input=users.encode('utf-8')) - if chpasswd.returncode != 0: - raise CalledProcessError(chpasswd.returncode, cmd=args, output=None) - - # pylint: disable=too-many-arguments def bootstrap(uri, dest, fmt='dir', @@ -117,8 +104,9 @@ def bootstrap(uri, dest, no_cache=no_cache, progress=prog).unpack(dest) - if root_password is not None: - set_root_password(dest, root_password) + if fmt == "dir" and root_password is not None: + logger.info("Setting password of the root account") + utils.set_root_password(dest, root_password) def set_logging_conf(loglevel=None): |