Exemplo n.º 1
0
    def create_group(self, name, members=None):
        group_add_cmd = ['groupadd', name]
        if util.system_is_snappy():
            group_add_cmd.append('--extrausers')
        if not members:
            members = []

        # Check if group exists, and then add it doesn't
        if util.is_group(name):
            LOG.warning("Skipping creation of existing group '%s'", name)
        else:
            try:
                util.subp(group_add_cmd)
                LOG.info("Created new group %s", name)
            except Exception:
                util.logexc(LOG, "Failed to create group %s", name)

        # Add members to the group, if so defined
        if len(members) > 0:
            for member in members:
                if not util.is_user(member):
                    LOG.warning("Unable to add group member '%s' to group '%s'"
                                "; user does not exist.", member, name)
                    continue

                util.subp(['usermod', '-a', '-G', name, member])
                LOG.info("Added user '%s' to group '%s'", member, name)
Exemplo n.º 2
0
 def test_id_in_os_release(self):
     """os-release containing ID=ubuntu-core is snappy."""
     orcontent = '\n'.join(['ID=ubuntu-core', ''])
     root_d = self.tmp_dir()
     helpers.populate_dir(root_d, {'etc/os-release': orcontent})
     self.reRoot(root_d)
     self.assertTrue(util.system_is_snappy())
Exemplo n.º 3
0
def _should_configure_on_empty_apt():
    # if no config was provided, should apt configuration be done?
    if util.system_is_snappy():
        return False, "system is snappy."
    if not (util.which('apt-get') or util.which('apt')):
        return False, "no apt commands."
    return True, "Apt is available."
Exemplo n.º 4
0
def _should_configure_on_empty_apt():
    # if no config was provided, should apt configuration be done?
    if util.system_is_snappy():
        return False, "system is snappy."
    if not (util.which('apt-get') or util.which('apt')):
        return False, "no apt commands."
    return True, "Apt is available."
Exemplo n.º 5
0
    def create_group(self, name, members=None):
        group_add_cmd = ['groupadd', name]
        if util.system_is_snappy():
            group_add_cmd.append('--extrausers')
        if not members:
            members = []

        # Check if group exists, and then add it doesn't
        if util.is_group(name):
            LOG.warning("Skipping creation of existing group '%s'", name)
        else:
            try:
                subp.subp(group_add_cmd)
                LOG.info("Created new group %s", name)
            except Exception:
                util.logexc(LOG, "Failed to create group %s", name)

        # Add members to the group, if so defined
        if len(members) > 0:
            for member in members:
                if not util.is_user(member):
                    LOG.warning(
                        "Unable to add group member '%s' to group '%s'"
                        "; user does not exist.", member, name)
                    continue

                subp.subp(['usermod', '-a', '-G', name, member])
                LOG.info("Added user '%s' to group '%s'", member, name)
Exemplo n.º 6
0
 def test_id_in_os_release(self):
     """os-release containing ID=ubuntu-core is snappy."""
     orcontent = '\n'.join(['ID=ubuntu-core', ''])
     root_d = self.tmp_dir()
     helpers.populate_dir(root_d, {'etc/os-release': orcontent})
     self.reRoot(root_d)
     self.assertTrue(util.system_is_snappy())
Exemplo n.º 7
0
def handle(name, cfg, cloud, log, args):
    cfgin = cfg.get('snappy')
    if not cfgin:
        LOG.debug('No snappy config provided, skipping')
        return

    if not(util.system_is_snappy()):
        LOG.debug("%s: system not snappy", name)
        return

    assertions = cfgin.get('assertions', [])
    if len(assertions) > 0:
        LOG.debug('Importing user-provided snap assertions')
        add_assertions(assertions)

    # Create a snap user if requested.
    # Snap systems contact the store with a user's email
    # and extract information needed to create a local user.
    # A user may provide a 'system-user' assertion which includes
    # the required information. Using such an assertion to create
    # a local user requires specifying 'known: true' in the supplied
    # user-data.
    usercfg = add_snap_user(cfg=cfgin)
    if usercfg:
        cloud.distro.create_user(usercfg.get('snapuser'), **usercfg)
Exemplo n.º 8
0
def handle(name, cfg, cloud, log, args):
    cfgin = cfg.get('snappy')
    if not cfgin:
        LOG.debug('No snappy config provided, skipping')
        return

    log.warning(
        'DEPRECATION: snap_config module will be dropped in 18.3 release.'
        ' Use snap module instead')
    if not(util.system_is_snappy()):
        LOG.debug("%s: system not snappy", name)
        return

    assertions = cfgin.get('assertions', [])
    if len(assertions) > 0:
        LOG.debug('Importing user-provided snap assertions')
        add_assertions(assertions)

    # Create a snap user if requested.
    # Snap systems contact the store with a user's email
    # and extract information needed to create a local user.
    # A user may provide a 'system-user' assertion which includes
    # the required information. Using such an assertion to create
    # a local user requires specifying 'known: true' in the supplied
    # user-data.
    usercfg = add_snap_user(cfg=cfgin)
    if usercfg:
        cloud.distro.create_user(usercfg.get('snapuser'), **usercfg)
Exemplo n.º 9
0
def handle(name, cfg, cloud, log, args):
    cfgin = cfg.get('snappy')
    if not cfgin:
        cfgin = {}
    mycfg = util.mergemanydict([cfgin, BUILTIN_CFG])

    sys_snappy = str(mycfg.get("system_snappy", "auto"))
    if util.is_false(sys_snappy):
        LOG.debug("%s: System is not snappy. disabling", name)
        return

    if sys_snappy.lower() == "auto" and not (util.system_is_snappy()):
        LOG.debug("%s: 'auto' mode, and system not snappy", name)
        return

    log.warning('DEPRECATION: snappy module will be dropped in 18.3 release.'
                ' Use snap module instead')

    set_snappy_command()

    pkg_ops = get_package_ops(packages=mycfg['packages'],
                              configs=mycfg['config'],
                              fspath=mycfg['packages_dir'])

    fails = []
    for pkg_op in pkg_ops:
        try:
            render_snap_op(**pkg_op)
        except Exception as e:
            fails.append((
                pkg_op,
                e,
            ))
            LOG.warning("'%s' failed for '%s': %s", pkg_op['op'],
                        pkg_op['name'], e)

    # Default to disabling SSH
    ssh_enabled = mycfg.get('ssh_enabled', "auto")

    # If the user has not explicitly enabled or disabled SSH, then enable it
    # when password SSH authentication is requested or there are SSH keys
    if ssh_enabled == "auto":
        user_ssh_keys = cloud.get_public_ssh_keys() or None
        password_auth_enabled = cfg.get('ssh_pwauth', False)
        if user_ssh_keys:
            LOG.debug("Enabling SSH, ssh keys found in datasource")
            ssh_enabled = True
        elif cfg.get('ssh_authorized_keys'):
            LOG.debug("Enabling SSH, ssh keys found in config")
        elif password_auth_enabled:
            LOG.debug("Enabling SSH, password authentication requested")
            ssh_enabled = True
    elif ssh_enabled not in (True, False):
        LOG.warning("Unknown value '%s' in ssh_enabled", ssh_enabled)

    disable_enable_ssh(ssh_enabled)

    if fails:
        raise Exception("failed to install/configure snaps")
Exemplo n.º 10
0
 def test_bad_content_in_os_release_no_effect(self, m_cmdline):
     """malformed os-release should not raise exception."""
     m_cmdline.return_value = 'root=/dev/sda'
     orcontent = '\n'.join(['IDubuntu-core', ''])
     root_d = self.tmp_dir()
     helpers.populate_dir(root_d, {'etc/os-release': orcontent})
     self.reRoot()
     self.assertFalse(util.system_is_snappy())
Exemplo n.º 11
0
 def test_system_image_config_dir_is_snappy(self, m_cmdline):
     """Existence of /etc/system-image/config.d indicates snappy."""
     m_cmdline.return_value = 'root=/dev/sda'
     root_d = self.tmp_dir()
     helpers.populate_dir(
         root_d, {'etc/system-image/config.d/my.file': "_unused"})
     self.reRoot(root_d)
     self.assertTrue(util.system_is_snappy())
Exemplo n.º 12
0
 def test_channel_ini_with_snappy_is_snappy(self, m_cmdline):
     """A Channel.ini file with 'ubuntu-core' indicates snappy."""
     m_cmdline.return_value = 'root=/dev/sda'
     root_d = self.tmp_dir()
     content = '\n'.join(["[Foo]", "source = 'ubuntu-core'", ""])
     helpers.populate_dir(root_d, {'etc/system-image/channel.ini': content})
     self.reRoot(root_d)
     self.assertTrue(util.system_is_snappy())
Exemplo n.º 13
0
 def test_system_image_config_dir_is_snappy(self, m_cmdline):
     """Existence of /etc/system-image/config.d indicates snappy."""
     m_cmdline.return_value = 'root=/dev/sda'
     root_d = self.tmp_dir()
     helpers.populate_dir(
         root_d, {'etc/system-image/config.d/my.file': "_unused"})
     self.reRoot(root_d)
     self.assertTrue(util.system_is_snappy())
Exemplo n.º 14
0
 def test_bad_content_in_os_release_no_effect(self, m_cmdline):
     """malformed os-release should not raise exception."""
     m_cmdline.return_value = 'root=/dev/sda'
     orcontent = '\n'.join(['IDubuntu-core', ''])
     root_d = self.tmp_dir()
     helpers.populate_dir(root_d, {'etc/os-release': orcontent})
     self.reRoot()
     self.assertFalse(util.system_is_snappy())
Exemplo n.º 15
0
 def test_snap_core_in_cmdline_is_snappy(self, m_cmdline):
     """The string snap_core= in kernel cmdline indicates snappy."""
     cmdline = ("BOOT_IMAGE=(loop)/kernel.img root=LABEL=writable "
                "snap_core=core_x1.snap snap_kernel=pc-kernel_x1.snap ro "
                "net.ifnames=0 init=/lib/systemd/systemd console=tty1 "
                "console=ttyS0 panic=-1")
     m_cmdline.return_value = cmdline
     self.assertTrue(util.system_is_snappy())
     self.assertTrue(m_cmdline.call_count > 0)
Exemplo n.º 16
0
 def test_channel_ini_with_snappy_is_snappy(self, m_cmdline):
     """A Channel.ini file with 'ubuntu-core' indicates snappy."""
     m_cmdline.return_value = 'root=/dev/sda'
     root_d = self.tmp_dir()
     content = '\n'.join(["[Foo]", "source = 'ubuntu-core'", ""])
     helpers.populate_dir(
         root_d, {'etc/system-image/channel.ini': content})
     self.reRoot(root_d)
     self.assertTrue(util.system_is_snappy())
Exemplo n.º 17
0
 def test_snap_core_in_cmdline_is_snappy(self, m_cmdline):
     """The string snap_core= in kernel cmdline indicates snappy."""
     cmdline = (
         "BOOT_IMAGE=(loop)/kernel.img root=LABEL=writable "
         "snap_core=core_x1.snap snap_kernel=pc-kernel_x1.snap ro "
         "net.ifnames=0 init=/lib/systemd/systemd console=tty1 "
         "console=ttyS0 panic=-1")
     m_cmdline.return_value = cmdline
     self.assertTrue(util.system_is_snappy())
     self.assertTrue(m_cmdline.call_count > 0)
Exemplo n.º 18
0
 def preferred_ntp_clients(self):
     """The preferred ntp client is dependent on the version."""
     if not self._preferred_ntp_clients:
         (_name, _version, codename) = util.system_info()['dist']
         # Xenial cloud-init only installed ntp, UbuntuCore has timesyncd.
         if codename == "xenial" and not util.system_is_snappy():
             self._preferred_ntp_clients = ['ntp']
         else:
             self._preferred_ntp_clients = (
                 copy.deepcopy(PREFERRED_NTP_CLIENTS))
     return self._preferred_ntp_clients
Exemplo n.º 19
0
 def preferred_ntp_clients(self):
     """The preferred ntp client is dependent on the version."""
     if not self._preferred_ntp_clients:
         (_name, _version, codename) = util.system_info()['dist']
         # Xenial cloud-init only installed ntp, UbuntuCore has timesyncd.
         if codename == "xenial" and not util.system_is_snappy():
             self._preferred_ntp_clients = ['ntp']
         else:
             self._preferred_ntp_clients = (
                 copy.deepcopy(PREFERRED_NTP_CLIENTS))
     return self._preferred_ntp_clients
Exemplo n.º 20
0
def ntp_installable():
    """Check if we can install ntp package

    Ubuntu-Core systems do not have an ntp package available, so
    we always return False.  Other systems require package managers to install
    the ntp package If we fail to find one of the package managers, then we
    cannot install ntp.
    """
    if util.system_is_snappy():
        return False

    if any(map(util.which, ['apt-get', 'dnf', 'yum', 'zypper'])):
        return True

    return False
Exemplo n.º 21
0
def apply_apt(cfg, cloud, target):
    # cfg is the 'apt' top level dictionary already in 'v3' format.
    if not cfg:
        # no config was provided.  If apt configuration does not seem
        # necessary on this system, then return.
        if util.system_is_snappy():
            LOG.debug("Nothing to do: No apt config and running on snappy")
            return
        if not (util.which('apt-get') or util.which('apt')):
            LOG.debug("Nothing to do: No apt config and no apt commands")
            return

    LOG.debug("handling apt config: %s", cfg)

    release = util.lsb_release(target=target)['codename']
    arch = util.get_architecture(target)
    mirrors = find_apt_mirror_info(cfg, cloud, arch=arch)
    LOG.debug("Apt Mirror info: %s", mirrors)

    if util.is_false(cfg.get('preserve_sources_list', False)):
        generate_sources_list(cfg, release, mirrors, cloud)
        rename_apt_lists(mirrors, target)

    try:
        apply_apt_config(cfg, APT_PROXY_FN, APT_CONFIG_FN)
    except (IOError, OSError):
        LOG.exception("Failed to apply proxy or apt config info:")

    # Process 'apt_source -> sources {dict}'
    if 'sources' in cfg:
        params = mirrors
        params['RELEASE'] = release
        params['MIRROR'] = mirrors["MIRROR"]

        matcher = None
        matchcfg = cfg.get('add_apt_repo_match', ADD_APT_REPO_MATCH)
        if matchcfg:
            matcher = re.compile(matchcfg).search

        add_apt_sources(cfg['sources'],
                        cloud,
                        target=target,
                        template_params=params,
                        aa_repo_match=matcher)
Exemplo n.º 22
0
 def test_nothing_found_is_not_snappy(self, m_cmdline):
     """If no positive identification, then not snappy."""
     m_cmdline.return_value = 'root=/dev/sda'
     self.reRoot()
     self.assertFalse(util.system_is_snappy())
     self.assertTrue(m_cmdline.call_count > 0)
Exemplo n.º 23
0
    def add_user(self, name, **kwargs):
        """
        Add a user to the system using standard GNU tools
        """
        if util.is_user(name):
            LOG.info("User %s already exists, skipping." % name)
            return

        if 'create_groups' in kwargs:
            create_groups = kwargs.pop('create_groups')
        else:
            create_groups = True

        adduser_cmd = ['useradd', name]
        log_adduser_cmd = ['useradd', name]
        if util.system_is_snappy():
            adduser_cmd.append('--extrausers')
            log_adduser_cmd.append('--extrausers')

        # Since we are creating users, we want to carefully validate the
        # inputs. If something goes wrong, we can end up with a system
        # that nobody can login to.
        adduser_opts = {
            "gecos": '--comment',
            "homedir": '--home',
            "primary_group": '--gid',
            "uid": '--uid',
            "groups": '--groups',
            "passwd": '--password',
            "shell": '--shell',
            "expiredate": '--expiredate',
            "inactive": '--inactive',
            "selinux_user": '******',
        }

        adduser_flags = {
            "no_user_group": '--no-user-group',
            "system": '--system',
            "no_log_init": '--no-log-init',
        }

        redact_opts = ['passwd']

        # support kwargs having groups=[list] or groups="g1,g2"
        groups = kwargs.get('groups')
        if groups:
            if isinstance(groups, (list, tuple)):
                # kwargs.items loop below wants a comma delimeted string
                # that can go right through to the command.
                kwargs['groups'] = ",".join(groups)
            else:
                groups = groups.split(",")

            primary_group = kwargs.get('primary_group')
            if primary_group:
                groups.append(primary_group)

        if create_groups and groups:
            for group in groups:
                if not util.is_group(group):
                    self.create_group(group)
                    LOG.debug("created group %s for user %s", name, group)

        # Check the values and create the command
        for key, val in kwargs.items():

            if key in adduser_opts and val and isinstance(val, str):
                adduser_cmd.extend([adduser_opts[key], val])

                # Redact certain fields from the logs
                if key in redact_opts:
                    log_adduser_cmd.extend([adduser_opts[key], 'REDACTED'])
                else:
                    log_adduser_cmd.extend([adduser_opts[key], val])

            elif key in adduser_flags and val:
                adduser_cmd.append(adduser_flags[key])
                log_adduser_cmd.append(adduser_flags[key])

        # Don't create the home directory if directed so or if the user is a
        # system user
        if 'no_create_home' in kwargs or 'system' in kwargs:
            adduser_cmd.append('-M')
            log_adduser_cmd.append('-M')
        else:
            adduser_cmd.append('-m')
            log_adduser_cmd.append('-m')

        # Run the command
        LOG.debug("Adding user %s", name)
        try:
            util.subp(adduser_cmd, logstring=log_adduser_cmd)
        except Exception as e:
            util.logexc(LOG, "Failed to create user %s", name)
            raise e
Exemplo n.º 24
0
    def add_user(self, name, **kwargs):
        """
        Add a user to the system using standard GNU tools
        """
        # XXX need to make add_user idempotent somehow as we
        # still want to add groups or modify SSH keys on pre-existing
        # users in the image.
        if util.is_user(name):
            LOG.info("User %s already exists, skipping.", name)
            return

        if 'create_groups' in kwargs:
            create_groups = kwargs.pop('create_groups')
        else:
            create_groups = True

        useradd_cmd = ['useradd', name]
        log_useradd_cmd = ['useradd', name]
        if util.system_is_snappy():
            useradd_cmd.append('--extrausers')
            log_useradd_cmd.append('--extrausers')

        # Since we are creating users, we want to carefully validate the
        # inputs. If something goes wrong, we can end up with a system
        # that nobody can login to.
        useradd_opts = {
            "gecos": '--comment',
            "homedir": '--home',
            "primary_group": '--gid',
            "uid": '--uid',
            "groups": '--groups',
            "passwd": '--password',
            "shell": '--shell',
            "expiredate": '--expiredate',
            "inactive": '--inactive',
            "selinux_user": '******',
        }

        useradd_flags = {
            "no_user_group": '--no-user-group',
            "system": '--system',
            "no_log_init": '--no-log-init',
        }

        redact_opts = ['passwd']

        # support kwargs having groups=[list] or groups="g1,g2"
        groups = kwargs.get('groups')
        if groups:
            if isinstance(groups, str):
                groups = groups.split(",")

            # remove any white spaces in group names, most likely
            # that came in as a string like: groups: group1, group2
            groups = [g.strip() for g in groups]

            # kwargs.items loop below wants a comma delimeted string
            # that can go right through to the command.
            kwargs['groups'] = ",".join(groups)

            primary_group = kwargs.get('primary_group')
            if primary_group:
                groups.append(primary_group)

        if create_groups and groups:
            for group in groups:
                if not util.is_group(group):
                    self.create_group(group)
                    LOG.debug("created group '%s' for user '%s'", group, name)

        # Check the values and create the command
        for key, val in sorted(kwargs.items()):

            if key in useradd_opts and val and isinstance(val, str):
                useradd_cmd.extend([useradd_opts[key], val])

                # Redact certain fields from the logs
                if key in redact_opts:
                    log_useradd_cmd.extend([useradd_opts[key], 'REDACTED'])
                else:
                    log_useradd_cmd.extend([useradd_opts[key], val])

            elif key in useradd_flags and val:
                useradd_cmd.append(useradd_flags[key])
                log_useradd_cmd.append(useradd_flags[key])

        # Don't create the home directory if directed so or if the user is a
        # system user
        if kwargs.get('no_create_home') or kwargs.get('system'):
            useradd_cmd.append('-M')
            log_useradd_cmd.append('-M')
        else:
            useradd_cmd.append('-m')
            log_useradd_cmd.append('-m')

        # Run the command
        LOG.debug("Adding user %s", name)
        try:
            subp.subp(useradd_cmd, logstring=log_useradd_cmd)
        except Exception as e:
            util.logexc(LOG, "Failed to create user %s", name)
            raise e
Exemplo n.º 25
0
    def add_user(self, name, **kwargs):
        """
        Add a user to the system using standard GNU tools
        """
        # XXX need to make add_user idempotent somehow as we
        # still want to add groups or modify ssh keys on pre-existing
        # users in the image.
        if util.is_user(name):
            LOG.info("User %s already exists, skipping.", name)
            return

        if 'create_groups' in kwargs:
            create_groups = kwargs.pop('create_groups')
        else:
            create_groups = True

        adduser_cmd = ['useradd', name]
        log_adduser_cmd = ['useradd', name]
        if util.system_is_snappy():
            adduser_cmd.append('--extrausers')
            log_adduser_cmd.append('--extrausers')

        # Since we are creating users, we want to carefully validate the
        # inputs. If something goes wrong, we can end up with a system
        # that nobody can login to.
        adduser_opts = {
            "gecos": '--comment',
            "homedir": '--home',
            "primary_group": '--gid',
            "uid": '--uid',
            "groups": '--groups',
            "passwd": '--password',
            "shell": '--shell',
            "expiredate": '--expiredate',
            "inactive": '--inactive',
            "selinux_user": '******',
        }

        adduser_flags = {
            "no_user_group": '--no-user-group',
            "system": '--system',
            "no_log_init": '--no-log-init',
        }

        redact_opts = ['passwd']

        # support kwargs having groups=[list] or groups="g1,g2"
        groups = kwargs.get('groups')
        if groups:
            if isinstance(groups, six.string_types):
                groups = groups.split(",")

            # remove any white spaces in group names, most likely
            # that came in as a string like: groups: group1, group2
            groups = [g.strip() for g in groups]

            # kwargs.items loop below wants a comma delimeted string
            # that can go right through to the command.
            kwargs['groups'] = ",".join(groups)

            primary_group = kwargs.get('primary_group')
            if primary_group:
                groups.append(primary_group)

        if create_groups and groups:
            for group in groups:
                if not util.is_group(group):
                    self.create_group(group)
                    LOG.debug("created group '%s' for user '%s'", group, name)

        # Check the values and create the command
        for key, val in sorted(kwargs.items()):

            if key in adduser_opts and val and isinstance(val, str):
                adduser_cmd.extend([adduser_opts[key], val])

                # Redact certain fields from the logs
                if key in redact_opts:
                    log_adduser_cmd.extend([adduser_opts[key], 'REDACTED'])
                else:
                    log_adduser_cmd.extend([adduser_opts[key], val])

            elif key in adduser_flags and val:
                adduser_cmd.append(adduser_flags[key])
                log_adduser_cmd.append(adduser_flags[key])

        # Don't create the home directory if directed so or if the user is a
        # system user
        if kwargs.get('no_create_home') or kwargs.get('system'):
            adduser_cmd.append('-M')
            log_adduser_cmd.append('-M')
        else:
            adduser_cmd.append('-m')
            log_adduser_cmd.append('-m')

        # Run the command
        LOG.debug("Adding user %s", name)
        try:
            util.subp(adduser_cmd, logstring=log_adduser_cmd)
        except Exception as e:
            util.logexc(LOG, "Failed to create user %s", name)
            raise e
Exemplo n.º 26
0
 def test_nothing_found_is_not_snappy(self, m_cmdline):
     """If no positive identification, then not snappy."""
     m_cmdline.return_value = 'root=/dev/sda'
     self.reRoot()
     self.assertFalse(util.system_is_snappy())
     self.assertTrue(m_cmdline.call_count > 0)