Example #1
0
File: agent.py Project: allgi/mmc
    def run(self):
        # If umask = 0077, created files will be rw for effective user only
        # If umask = 0007, they will be rw for effective user and group only
        os.umask(self.config.umask)
        os.setegid(self.config.egid)
        os.seteuid(self.config.euid)

        # Daemonize early
        if self.daemon:
            self.lock.acquire()
            self.daemonize()

        # Do all kind of initialization
        try:
            ret = self.initialize()
        finally:
            # Tell the father how to return, and let him return (release)
            if self.daemon:
                self.state = ret
                self.lock.release()

        if ret:
            return ret

        reactor.run()
Example #2
0
def symlink(src, dst, relative_to=None):
    """
    Creates a symbolic link at `dst` to the file at `src`. If `src` is a symlink the
    link will be followed to get the actual file that will be linked at `dst`. If `dst`
    is a symlink then it will be removed.

    Args:
        src (str): The path to the file that will be linked.
        dst (str): The path at which the link to the file at `src` should be created.

    """

    uid = os.geteuid()
    gid = os.getegid()

    os.setegid(33)
    os.seteuid(33)

    if relative_to:
        os.chdir(relative_to)

    if os.path.islink(src):
        src = os.readlink(src) if not relative_to else os.path.relpath(os.readlink(src))

    if os.path.islink(dst):
        os.unlink(dst)

    os.symlink(src, dst)

    os.setegid(gid)
    os.seteuid(uid)
Example #3
0
def copy_or_symlink(src, dst, logger=None):
    """
    Copies the file at `src` to `dst`. If `src` is a symlink the link will be
    followed to get the file that will be copied. If `dst` is a symlink then it will
    be removed.

    Args:
        src (str): The path to the file that will be copied.
        dst (str): The path to where the src file should be copied to.

    """

    uid = os.geteuid()
    gid = os.getegid()

    os.setegid(33)
    os.seteuid(33)

    if logger:
        logger.debug([src, dst])
    if os.path.islink(src):
        linkto = os.readlink(src)
        os.symlink(linkto, dst)
    else:
        try:
            shutil.copy(src, dst)
        except shutil.SameFileError:
            if os.path.islink(dst):
                os.unlink(dst)
                shutil.copy(src, dst)
        except Exception as err:
            logger.error(err)

    os.setegid(gid)
    os.seteuid(uid)
Example #4
0
def _create_new_key(keystone_user_id, keystone_group_id):
    """Securely create a new encryption key.

    Create a new key that is readable by the Keystone group and Keystone user.
    """
    key = fernet.Fernet.generate_key()  # key is bytes

    # This ensures the key created is not world-readable
    old_umask = os.umask(0o177)
    if keystone_user_id and keystone_group_id:
        old_egid = os.getegid()
        old_euid = os.geteuid()
        os.setegid(keystone_group_id)
        os.seteuid(keystone_user_id)
    elif keystone_user_id or keystone_group_id:
        LOG.warning(_LW(
            'Unable to change the ownership of the new key without a keystone '
            'user ID and keystone group ID both being provided: %s') %
            CONF.fernet_tokens.key_repository)
    # Determine the file name of the new key
    key_file = os.path.join(CONF.fernet_tokens.key_repository, '0')
    try:
        with open(key_file, 'w') as f:
            f.write(key.decode('utf-8'))  # convert key to str for the file.
    finally:
        # After writing the key, set the umask back to it's original value. Do
        # the same with group and user identifiers if a Keystone group or user
        # was supplied.
        os.umask(old_umask)
        if keystone_user_id and keystone_group_id:
            os.seteuid(old_euid)
            os.setegid(old_egid)

    LOG.info(_LI('Created a new key: %s'), key_file)
Example #5
0
def _run_check(cmd_kwargs, onlyif, unless, cwd, user, group, shell):
    '''
    Execute the onlyif logic and return data if the onlyif fails
    '''
    ret = {}

    if group:
        try:
            egid = grp.getgrnam(group).gr_gid
            if not __opts__['test']:
                os.setegid(egid)
        except KeyError:
            ret['comment'] = 'The group {0} is not available'.format(group)
            return {'comment': 'The group {0} is not available'.format(group),
                    'result': False}

    if onlyif:
        if __salt__['cmd.retcode'](onlyif, **cmd_kwargs) != 0:
            ret['comment'] = 'onlyif exec failed'
            ret['result'] = True
            return {'comment': 'onlyif exec failed',
                    'result': True}

    if unless:
        if __salt__['cmd.retcode'](unless, **cmd_kwargs) == 0:
            return {'comment': 'unless executed successfully',
                    'result': True}
    # No reason to stop, return True
    return True
 def vfs_op_success(self, filename, dentry, args, filetype="f", create=False, copy_up=False,
                    hardlink_to=None):
     if "as_bin" in args:
         self.verbosef("os.seteuid(0)")
         os.seteuid(0)
         self.verbosef("os.setegid(0)")
         os.setegid(0)
     want_error = args["err"]
     if want_error:
         raise TestError(filename + ": Expected error (" +
                         os.strerror(want_error) + ") was not produced")
     if dentry.is_negative():
         if not create:
             if filetype == "d":
                 raise TestError(filename + ": Directory was created unexpectedly")
             elif filetype == "s":
                 raise TestError(filename + ": Symlink was created unexpectedly")
             else:
                 raise TestError(filename + ": File was created unexpectedly")
         if not hardlink_to:
             dentry.created(inode(filetype))
         else:
             dentry.created(hardlink_to, on_upper = dentry.on_upper())
     else:
         if copy_up:
             dentry.copied_up()
     self.check_layer(filename)
Example #7
0
def drop_privileges(user: pwd.struct_passwd, group: grp.struct_group, permanent: bool = True):
    """
    Drop root privileges and change to something more safe.

    :param user: The tuple with user info
    :param group: The tuple with group info
    :param permanent: Whether we want to drop just the euid (temporary), or all uids (permanent)
    """
    # Restore euid=0 if we have previously changed it
    if os.geteuid() != 0 and os.getuid() == 0:
        restore_privileges()

    if os.geteuid() != 0:
        raise RuntimeError("Not running as root: cannot change uid/gid to {}/{}".format(user.pw_name, group.gr_name))

    # Remove group privileges
    os.setgroups([])

    if permanent:
        os.setgid(group.gr_gid)
        os.setuid(user.pw_uid)
    else:
        os.setegid(group.gr_gid)
        os.seteuid(user.pw_uid)

    # Ensure a very conservative umask
    os.umask(0o077)

    if permanent:
        logger.debug("Permanently dropped privileges to {}/{}".format(user.pw_name, group.gr_name))
    else:
        logger.debug("Dropped privileges to {}/{}".format(user.pw_name, group.gr_name))
Example #8
0
def init(*configFiles):
    global _svr
    if _svr:
        raise RuntimeError, "already initialized"

    loadConfig(*configFiles)
    configDefaults()
    updateConfig()
    configLogging()    

    # set effective user/group, if necessary
    isroot=os.getuid()==0
    run_user=Configuration.run_user
    run_group=Configuration.run_group
    if isroot and run_user is None:
        raise RuntimeError, "won't run as root with out run_user being defined"
    if run_group is not None:
        gid=grp.getnrnam(run_group)[2]
        if hasattr(os, 'setegid'):
            os.setegid(gid)
        #else?
    if run_user is not None:
        uid=pwd.getpwnam(run_user)[2]
        if hasattr(os, 'seteuid'):
            os.seteuid(uid)
        #else?

    loadServices()
    
    # revv 'er up
    _svr=Server(configFiles)
    _svr.mainloop()
Example #9
0
def setup_container_users():
    r"""
    Create container users and setup SSH access.
    """
    log.info("setting up users in the containter")
    check_call("addgroup --gid {GID} {group}")
    check_call("adduser --uid {server_ID} --ingroup {group} --gecos '' "
               "--disabled-password {server}")
    check_call("adduser --uid {worker_ID} --ingroup {group} --gecos '' "
               "--disabled-password {worker}")

    shome = os.path.join("/home", users["server"])
    whome = os.path.join("/home", users["worker"])
    os.chdir(shome)
    os.setegid(users["GID"])
    os.seteuid(users["server_ID"])
    os.mkdir(".ssh", 0o700)
    check_call("ssh-keygen -q -N '' -f .ssh/id_rsa")

    os.chdir(whome)
    os.setuid(0)
    os.seteuid(users["worker_ID"])
    os.mkdir(".ssh", 0o700)
    files_to_lock = ".ssh .bashrc .bash_profile .bash_logout .profile"
    check_call("touch " + files_to_lock)
    os.setuid(0)
    shutil.copy2(os.path.join(shome, ".ssh/id_rsa.pub"),
                 ".ssh/authorized_keys")
    os.chown(".ssh/authorized_keys", users["worker_ID"], users["GID"])
    # Get the localhost in the known_hosts file.
    check_call("su -l {server} -c "
               "'ssh -q -oStrictHostKeyChecking=no {worker}@localhost whoami'")
    for f in files_to_lock.split():
        check_call("chattr -R +i " + f)
Example #10
0
def drop_privileges():
    if 'SUDO_GID' in os.environ:
        gid = int(os.environ['SUDO_GID'])
        os.setegid(gid)
    if 'SUDO_UID' in os.environ:
        uid = int(os.environ['SUDO_UID'])
        os.seteuid(uid)
Example #11
0
def main():
    #change to data directory if needed
    os.chdir(workdir)
    # Redirect outputs to a logfile
    sys.stdout = sys.stderr = Log(open('%s/%s' % (workdir, logfile), 'a+'))
    # ensure the that the daemon runs a normal user
    os.setegid(0)     # set group
    os.seteuid(0)     # set user
    #start the user program here:
    print 'Daemon running at ' + time.strftime("%Y/%m/%d %H.%M.%S")

    s = socket(AF_INET, SOCK_STREAM)    # Create the TCP Socket
    s.bind((statHost, statPort))        # bind it to the server port
    s.listen(child)                     # allow X simultaneous pending connections
    (connection, address) = s.accept()  # connection is a new socket
    try:
        while 1:
            data = connection.recv(buf)  # receive up to 1K bytes
            if data:
                store(address[0])
                r = data.split()
                result = address[0] + ' '
                for item in r:
                    result += item + ' '
                print result
                #smsfile = open(filename, 'w+')
                #smsfile.write(msg)
                #smsfile.	close()
    except KeyboardInterrupt:
        stopd()
        #	print 'Daemon normal exit at '+time.strftime("%Y/%m/%d %H.%M.%S")
    #	os.remove('%s/%s' % (workdir,pidfile))
    connection.close()              # close socket
Example #12
0
def switch_to_current_user():
    """Switch euid and guid to current user if current user is root"""
    if os.geteuid() != 0:
        return
    # fallback to root user if no SUDO_GID (should be su - root)
    os.setegid(int(os.getenv("SUDO_GID", default=0)))
    os.seteuid(int(os.getenv("SUDO_UID", default=0)))
Example #13
0
def tor_new_process():
    """
    Drops privileges to TOR_USER user and start a new Tor process
    """
    debian_tor_uid = getpwnam(TOR_USER).pw_uid
    debian_tor_gid = getpwnam(TOR_USER).pw_gid
    os.setgid(debian_tor_gid)
    os.setuid(debian_tor_uid)
    os.setegid(debian_tor_gid)
    os.seteuid(debian_tor_uid)
    os.environ['HOME'] = "/var/lib/tor"

    tor_process = stem.process.launch_tor_with_config(
      config = {
        'SocksPort': '6666',
        'ControlPort': '6969',
        'DNSPort': '9053',
        'DNSListenAddress': '127.0.0.1',
        'AutomapHostsOnResolve': '1',
        'AutomapHostsSuffixes': '.exit,.onion',
        'VirtualAddrNetwork': '10.192.0.0/10',
        'TransPort': '9040',
        'TransListenAddress': '127.0.0.1',
        'AvoidDiskWrites': '1',
        'WarnUnsafeSocks': '1',
      })
Example #14
0
 def _switch_process_owner(self, user, group):
     try:
         seteuid(getpwnam(user).pw_uid)
         setegid(getgrnam(group).gr_gid)
     except OSError, e:
         raise UnixSetupError('Error - Couldn\'t switch process owner \'{:}.{:}\'. Details {:}.'.format(
             user, group, e))
Example #15
0
    def setuid(self):
        """
        Set user and group ID of the process

        If ``self.group`` is not defined, then this method uses the group ID of
        the ``self.user``.

        Returns a tuple containing the active user and group IDs.
        """
        if not has_user:
            logging.warn('User switching is disabled on this OS')
            return
        logging.debug('Setting process UID and GID')
        pwinfo = pwd.getpwnam(self.user)
        uid = pwinfo.pw_uid
        os.setuid(uid)
        os.seteuid(uid)
        if self.group:
            logging.debug('Using specified group for GID')
            gid = grp.getgrpnam(self.group).grp_gid
        else:
            logging.debug('Using specified user for GID')
            gid = pwinfo.pw_gid
        os.setgid(gid)
        os.setegid(gid)
        logging.debug('Process UID=%s and GID=%s', uid, gid)
        return uid, gid
Example #16
0
 def _process_securely(self, operation, path, request, *args, **kw):
     user = request.user_object()
     groups = os.getgroups()
     is_root = not os.getuid()
     uid = os.geteuid()
     gid = os.getegid()
     if not is_root:
         msg = (
             "Framework is not running as root so effective uid "
             "and gid are not being changed prior to doing %s: "
             "%s" % (request.get_command(), path)
         )
         msglog.log("FileRequestHandler", msglog.types.WARN, msg)
     else:
         if self.debug:
             msg = "%s command: file %s, user %s" % (request.get_command(), path, user.name())
             msglog.log(self.name, msglog.types.DB, msg)
         os.setgroups(user.group_ids())
         os.setegid(user.gid())
         os.seteuid(user.uid())
     try:
         result = operation(path, request, *args, **kw)
     finally:
         if is_root:
             os.seteuid(uid)
             os.setegid(gid)
             os.setgroups(groups)
     return result
Example #17
0
def fork_as(su, function, *args):
    """
    fork(), cd / to avoid keeping unused directories open, close all nonstandard
    file descriptors (to avoid capturing open sockets), fork() again (to avoid
    zombies) and call <function> with arguments <args> in the grandchild
    process. If <su> is not None, set our group and user ids appropriately in
    the child process.
    """
    child_pid = os.fork()
    if child_pid == 0:
        try:
            os.chdir('/')
            close_nonstandard_fds()
            if su:
                pw_ent = pwd.getpwnam(su)
                os.setegid(pw_ent[3])
                os.seteuid(pw_ent[2])
            child_pid = os.fork()
            if child_pid == 0:
                function(*args)
        except:
            os.seteuid(os.getuid())  # undo su so we can write the log file
            os.setegid(os.getgid())
            logger.log_exc("tools: fork_as")
        os._exit(0)
    else:
        os.waitpid(child_pid, 0)
Example #18
0
 def getRsaKeys(self, all = None):
     uidBefore = os.geteuid()
     os.seteuid(0)
     gidBefore = os.getgid()
     os.setegid(0)
     self._prepareSSHEnvironment()
     sshPrivateKey = os.path.join(dissomniag.config.dissomniag.configDir, dissomniag.config.dissomniag.rsaKeyPrivate)
     sshPrivateKey = os.path.abspath(sshPrivateKey)
     sshPublicKey = os.path.join(dissomniag.config.dissomniag.configDir, dissomniag.config.dissomniag.rsaKeyPublic)
     sshPublicKey = os.path.abspath(sshPublicKey)
     if not (os.path.exists(sshPrivateKey) and os.path.exists(sshPublicKey)):
         ret = subprocess.call(shlex.split("ssh-keygen -t rsa -q -f %s -P ''" % sshPrivateKey),
                         stdout = open('/dev/null', 'w'),
                         stderr = subprocess.STDOUT)
         if ret != 0:
             raise SSHKeyGenError()
         else:
             log.debug("New SSH Keys created")
         
             
     
     privateKeyString = file(sshPrivateKey, 'r').read()
     privateKey = keys.Key.fromString(privateKeyString)
     publicKeyString = file(sshPublicKey, 'r').read()
     publicKey = keys.Key.fromString(publicKeyString)
     
     self._checkRsaKeyAdded(sshPrivateKey, publicKeyString)
     os.setegid(gidBefore)
     os.seteuid(uidBefore)
     if all:
         return sshPrivateKey, privateKeyString, sshPublicKey, publicKeyString
     else:
         return publicKey, privateKey
Example #19
0
    def _drop_privileges(self, user=None, group=None):
        """
        Set user/group privileges
        """
        # FIXME: Handle permission exceptions

        # Set group privileges
        if group is None:
            group = self._config.get(
                plog.CFG_SECT_GLOBAL, plog.CFG_OPT_GROUP, None)
            group = self._config.get(self._name, plog.CFG_OPT_GROUP, group)
        if group is not None:
            import grp
            group_info = grp.getgrnam(group)
            os.setegid(group_info.gr_gid)

        # Set user privileges
        if user is None:
            user = self._config.get(
                plog.CFG_SECT_GLOBAL, plog.CFG_OPT_USER, None)
            user = self._config.get(self._name, plog.CFG_OPT_USER, user)
        if user is not None:
            import pwd
            user_info = pwd.getpwnam(user)
            os.seteuid(user_info.pw_uid)
Example #20
0
def stop(command, argv):
    parser = argparse.ArgumentParser(
        description="Critic administration interface: stop",
        prog="criticctl [options] stop")

    parser.parse_args(argv)

    import os
    import subprocess

    system_identity = configuration.base.SYSTEM_IDENTITY

    try:
        os.seteuid(0)
        os.setegid(0)
    except OSError:
        print >>sys.stderr, "ERROR: 'criticctl stop' must be run as root."
        return 1

    if configuration.base.WEB_SERVER_INTEGRATION == "apache":
        web_server_service = "apache2"
    elif configuration.base.WEB_SERVER_INTEGRATION in ("nginx+uwsgi", "uwsgi"):
        web_server_service = "uwsgi"
    else:
        web_server_service = None

    if web_server_service:
        subprocess.check_call(["service", web_server_service, "stop"])
    subprocess.check_call(["service", "critic-" + system_identity, "stop"])

    return 0
Example #21
0
def restart(command, argv):
    parser = argparse.ArgumentParser(
        description="Critic administration interface: restart",
        prog="criticctl [options] restart")

    parser.parse_args(argv)

    result = configtest("configtest", ["--quiet"])

    if result != 0:
        print >>sys.stderr, "ERROR: System configuration is not valid."
        return result

    import os
    import subprocess

    system_identity = configuration.base.SYSTEM_IDENTITY

    try:
        os.seteuid(0)
        os.setegid(0)
    except OSError:
        print >>sys.stderr, "ERROR: 'criticctl restart' must be run as root."
        return 1

    subprocess.check_call(["service", "apache2", "stop"])
    subprocess.check_call(["service", "critic-" + system_identity, "restart"])
    subprocess.check_call(["service", "apache2", "start"])

    return 0
Example #22
0
def ejecutar_comando_fuente(self, entrega, contexto_ejecucion, caso_de_prueba): #{{{
    path = contexto_ejecucion.build_path
    log.debug(_(u'ComandoFuente.ejecutar(path=%s, entrega=%s)'), path,
        entrega)
    if not self.activo:
        log.debug(_(u'Ignorando comando fuente porque esta inactivo'))
        return
    comando_ejecutado = entrega.add_comando_ejecutado(self)
    basetmp = contexto_ejecucion.build_temp_base_path
    unzip(self.archivos_entrada, path, # TODO try/except
        {self.STDIN: '%s.%s.stdin' % (basetmp, comando_ejecutado.id)})
    options = dict(
        close_fds=True,
        shell=True,
        preexec_fn=contexto_ejecucion.crear_preejecutor_fuente(self)
    )
    if os.path.exists('%s.%s.stdin' % (basetmp, comando_ejecutado.id)):
        options['stdin'] = file('%s.%s.stdin' % (basetmp, comando_ejecutado.id),
            'r')
    else:
        options['preexec_fn'].close_stdin = True
    a_guardar = set(self.archivos_a_guardar)
    zip_a_comparar = Multizip(self.archivos_a_comparar)
    a_comparar = set(zip_a_comparar.namelist())
    a_usar = frozenset(a_guardar | a_comparar)
    if self.STDOUTERR in a_usar:
        options['stdout'] = file('%s.%s.stdouterr' % (basetmp,
            comando_ejecutado.id), 'w')
        options['stderr'] = sp.STDOUT
    else:
        if self.STDOUT in a_usar:
            options['stdout'] = file('%s.%s.stdout' % (basetmp,
                comando_ejecutado.id), 'w')
        else:
            options['preexec_fn'].close_stdout = True
        if self.STDERR in a_usar:
            options['stderr'] = file('%s.%s.stderr' % (basetmp,
                comando_ejecutado.id), 'w')
        else:
            options['preexec_fn'].close_stderr = True
    comando = self.comando # FIXME tiene que diferenciarse de ComandoPrueba
    comando_ejecutado.inicio = datetime.now()
    log.debug(_(u'Ejecutando como root: %s'), comando)
    os.seteuid(0) # Dios! (para chroot)
    os.setegid(0)
    try:
        try:
            returncode = contexto_ejecucion.ejecutar(comando, options)
        except ProcessException as e:
            comando_ejecutado.exito = False
            comando_ejecutado.observaciones += str(e)
            if self.rechazar_si_falla:
                entrega.exito = False
            log.exception(_('Ha ocurrido un error inexperado en la ejecucion de la entrega. Comando: %s. Entrega: %s'), comando, entrega)
        finally:
            contexto_ejecucion.user_info.reset_permisos() # Mortal de nuevo
    except Exception, e:
        if hasattr(e, 'child_traceback'):
            log.error(_(u'Error en el hijo: %s'), e.child_traceback)
        raise
Example #23
0
 def impersonate_user(self, username, password):
     if (username == "anonymous") and self.has_user('anonymous'):
         username = self.anon_user
     uid = pwd.getpwnam(username).pw_uid
     gid = pwd.getpwnam(username).pw_gid
     os.setegid(gid)
     os.seteuid(uid)
Example #24
0
def regain_privileges():
    global _dropped_privileges
    assert _dropped_privileges is not None
    _dropped_privileges -= 1
    if _dropped_privileges == 0:
        os.seteuid(0)
        os.setegid(0)
Example #25
0
File: cmd.py Project: d1on/salt
def run(name,
        onlyif=None,
        unless=None,
        cwd='/root',
        user=None,
        group=None):
    '''
    Ensure that the named command is executed

    Arguments:
    name -- The command to run

    Keyword Argument:
    onlyif -- Only run the main command if this command returns true
    unless -- Only run the main command if this command returns False
    cwd -- Run the command from this directory, defaults to /root
    user -- Run the command as this user
    group -- run the command as this group
    '''
    ret = {'name': name,
           'changes': {},
           'result': False,
           'comment': ''}
    if onlyif:
        if __salt__['cmd.retcode'](onlyif) != 0:
            ret['comment'] = 'onlyif exec failed'
            ret['result'] = True
            return ret
    if unless:
        if __salt__['cmd.retcode'](unless) == 0:
            ret['comment'] = 'unless executed successfully'
            ret['result'] = True
            return ret
    if not os.path.isdir(cwd):
        ret['comment'] = 'Desired working directory is not available'
        return ret
    puid = os.geteuid()
    pgid = os.getegid()
    if group:
        try:
            egid = grp.getgrnam(group).gr_gid
            os.setegid(egid)
        except KeyError:
            ret['comment'] = 'The group ' + group + ' is not available'
            return ret
    if user:
        try:
            euid = pwd.getpwnam(user).pw_uid
            os.seteuid(euid)
        except KeyError:
            ret['comment'] = 'The user ' + user + ' is not available'
            return ret
    # Wow, we pased the test, run this sucker!
    cmd_all = __salt__['cmd.run_all'](name, cwd)
    ret['changes'] = cmd_all
    ret['result'] = not bool(cmd_all['retcode'])
    ret['comment'] = 'Command ' + name + ' run'
    os.seteuid(puid)
    os.setegid(pgid)
    return ret
Example #26
0
def drop_privileges(user='******', group='nogroup'):
    """
    Drop privileges if we're superuser by changing UID/GID to given user/group.
    """
    if os.geteuid() == 0:
        # Remove group privileges
        os.setgroups([])

        if group != 'root':
            try:
                newgid = grp.getgrnam(group).gr_gid
            except KeyError:
                raise RuntimeError("System group '%s' not found." % group)

            os.setgid(newgid)
            os.setegid(newgid)

        if user != 'root':
            try:
                newuid = pwd.getpwnam(user).pw_uid
            except KeyError:
                raise RuntimeError("System user '%s' not found." % user)

            os.setuid(newuid)
            os.seteuid(newuid)
Example #27
0
def run_command_safe(cb: types.FunctionType, uid=99, gid=99):
    """
    Run callback safely, dropping *effective* UID down to an unpriv user.

    This is a coroutine.
    :param cb: A callback function to call. This should be a coroutine.
    :param uid: The UID to drop to, by default `99`.
    :param gid: The gid to drop to, by default `99`.
    :return: The result of the command.
    """
    # Get current UID and GID.
    cuid, cgid = os.getuid(), os.getgid()
    # Drop our privileges temporarily.
    try:
        os.seteuid(uid)
        os.setegid(gid)
    except PermissionError:
        print("FAILED TO DROP PERMISSIONS - ARE WE RUNNING AS ROOT?", file=sys.stderr)
    # Run the command.
    res = yield from cb()
    # Reset our euid/egid.
    try:
        os.seteuid(cuid)
        os.setegid(cgid)
    except PermissionError:
        print("FAILED TO DROP PERMISSIONS - ARE WE RUNNING AS ROOT?", file=sys.stderr)
    return res
Example #28
0
def user_makedirs(target, u_uid, u_gid):
	os.setegid(u_gid)
	os.seteuid(u_uid)

	os.makedirs(target)
	os.seteuid(uid)
	os.setegid(gid)
Example #29
0
File: cmd.py Project: herlo/salt
def _run_check(cmd_kwargs, onlyif, unless, group):
    '''
    Execute the onlyif and unless logic. 
    Return a result dict if:
    * group is not available
    * onlyif failed (onlyif != 0)
    * unless succeeded (unless == 0)
    else return True
    '''
    if group and HAS_GRP:
        try:
            egid = grp.getgrnam(group).gr_gid
            if not __opts__['test']:
                os.setegid(egid)
        except KeyError:
            return {'comment': 'The group {0} is not available'.format(group),
                    'result': False}

    if onlyif:
        if __salt__['cmd.retcode'](onlyif, **cmd_kwargs) != 0:
            return {'comment': 'onlyif execution failed',
                    'result': True}

    if unless:
        if __salt__['cmd.retcode'](unless, **cmd_kwargs) == 0:
            return {'comment': 'unless execution succeeded',
                    'result': True}

    # No reason to stop, return True
    return True
Example #30
0
    def sync_trees(self,tree,dst,user,client):
        record = pwd.getpwnam(user)

        # temporarily grant access to the unpack staging area by modifying the
        # group of the top-level repository directory
        os.chown(self.localCopy,-1,record.pw_gid)

        # we do the sync operation as the specified user; so we need to fork
        # ourself again and change our user/group mode
        pid = os.fork()
        if pid != 0:
            # synchronously wait for the child to do its work
            os.wait()
            os.chown(self.localCopy,-1,0) # change back to root
            return

        # set effective permissions; we almost reproduce a login shell here
        # because we have to load up the user's supplementary group ids
        os.setegid(record.pw_gid)
        os.initgroups(user,record.pw_gid)
        os.seteuid(record.pw_uid)

        # redirect the process's stdout (underlying os-level redirection) to the
        # socket
        os.dup2(client.fileno(),1)
        os.dup2(client.fileno(),2)
        os.close(client.fileno())

        # exec rsync over this process to copy updated content to the
        # destination; we assume that rsync is installed on the system
        change_dir(self.localCopy)
        if tree[len(tree)-1] != '/':
            tree += '/' # rsync requires this
        os.execlp('rsync','rsync','--exclude=.git/','-rvu','--chmod=ugo=rwX',tree,dst)
Example #31
0
def run(name,
        onlyif=None,
        unless=None,
        cwd=None,
        user=None,
        group=None,
        shell=None,
        env=(),
        stateful=False,
        umask=None,
        quiet=False,
        timeout=None,
        **kwargs):
    '''
    Run a command if certain circumstances are met

    name
        The command to execute, remember that the command will execute with the
        path and permissions of the salt-minion.

    onlyif
        A command to run as a check, run the named command only if the command
        passed to the ``onlyif`` option returns true

    unless
        A command to run as a check, only run the named command if the command
        passed to the ``unless`` option returns false

    cwd
        The current working directory to execute the command in, defaults to
        /root

    user
        The user name to run the command as

    group
        The group context to run the command as

    shell
        The shell to use for execution, defaults to the shell grain

    env
        Pass in a list or dict of environment variables to be applied to the
        command upon execution

    stateful
        The command being executed is expected to return data about executing
        a state

    umask
        The umask (in octal) to use when running the command.

    quiet
        The command will be executed quietly, meaning no log entries of the
        actual command or its return data

    timeout
        If the command has not terminated after timeout seconds, send the
        subprocess sigterm, and if sigterm is ignored, follow up with sigkill
    '''
    ### NOTE: The keyword arguments in **kwargs are ignored in this state, but
    ###       cannot be removed from the function definition, otherwise the use
    ###       of unsupported arguments in a cmd.run state will result in a
    ###       traceback.

    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    if cwd and not os.path.isdir(cwd):
        ret['comment'] = 'Desired working directory is not available'
        return ret

    if env:
        if isinstance(env, basestring):
            try:
                env = yaml.safe_load(env)
            except Exception:
                _env = {}
                for var in env.split():
                    try:
                        key, val = var.split('=')
                        _env[key] = val
                    except ValueError:
                        ret['comment'] = \
                            'Invalid environmental var: "{0}"'.format(var)
                        return ret
                env = _env
        elif isinstance(env, dict):
            pass

        elif isinstance(env, list):
            _env = {}
            for comp in env:
                try:
                    if isinstance(comp, basestring):
                        _env.update(yaml.safe_load(comp))
                    if isinstance(comp, dict):
                        _env.update(comp)
                    else:
                        ret['comment'] = \
                            'Invalid environmental var: "{0}"'.format(env)
                        return ret
                except Exception:
                    _env = {}
                    for var in comp.split():
                        try:
                            key, val = var.split('=')
                            _env[key] = val
                        except ValueError:
                            ret['comment'] = \
                                'Invalid environmental var: "{0}"'.format(var)
                            return ret
            env = _env

    if HAS_GRP:
        pgid = os.getegid()

    cmd_kwargs = {
        'cwd': cwd,
        'runas': user,
        'shell': shell or __grains__['shell'],
        'env': env,
        'umask': umask,
        'quiet': quiet
    }

    try:
        cret = _run_check(cmd_kwargs, onlyif, unless, group)
        if isinstance(cret, dict):
            ret.update(cret)
            return ret

        # Wow, we passed the test, run this sucker!
        if not __opts__['test']:
            try:
                cmd_all = __salt__['cmd.run_all'](name,
                                                  timeout=timeout,
                                                  **cmd_kwargs)
            except CommandExecutionError as err:
                ret['comment'] = str(err)
                return ret

            ret['changes'] = cmd_all
            ret['result'] = not bool(cmd_all['retcode'])
            ret['comment'] = 'Command "{0}" run'.format(name)
            return _reinterpreted_state(ret) if stateful else ret
        ret['result'] = None
        ret['comment'] = 'Command "{0}" would have been executed'.format(name)
        return _reinterpreted_state(ret) if stateful else ret

    finally:
        if HAS_GRP:
            os.setegid(pgid)
Example #32
0
def run(name,
        onlyif=None,
        unless=None,
        cwd='/root',
        user=None,
        group=None,
        shell='/bin/sh',
        env=()):
    '''
    Run a command if certain circumstances are met

    name
        The command to execute, remember that the command will execute with the
        path and permissions of the salt-minion.

    onlyif
        A command to run as a check, run the named command only if the command
        passed to the ``onlyif`` option returns true

    unless
        A command to run as a check, only run the named command if the command
        passed to the ``unless`` option returns false

    cwd
        The current working directory to execute the command in, defaults to
        /root

    user
        The user name to run the command as

    group
        The group context to run the command as
    '''
    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    if onlyif:
        if __salt__['cmd.retcode'](onlyif) != 0:
            ret['comment'] = 'onlyif exec failed'
            ret['result'] = True
            return ret

    if unless:
        if __salt__['cmd.retcode'](unless) == 0:
            ret['comment'] = 'unless executed successfully'
            ret['result'] = True
            return ret

    if not os.path.isdir(cwd):
        ret['comment'] = 'Desired working directory is not available'
        return ret

    pgid = os.getegid()

    if group:
        try:
            egid = grp.getgrnam(group).gr_gid
            if not __opts__['test']:
                os.setegid(egid)
        except KeyError:
            ret['comment'] = 'The group {0} is not available'.format(group)
            return ret

    if env:
        _env = {}
        for var in env.split():
            try:
                k, v = var.split('=')
                _env[k] = v
            except ValueError:
                ret['comment'] = 'Invalid enviromental var: "{0}"'.format(var)
                return ret
        env = _env

    # Wow, we passed the test, run this sucker!
    if not __opts__['test']:
        try:
            cmd_all = __salt__['cmd.run_all'](name,
                                              cwd,
                                              runas=user,
                                              shell=shell,
                                              env=env)
        except CommandExecutionError as e:
            ret['comment'] = e
            return ret

        ret['changes'] = cmd_all
        ret['result'] = not bool(cmd_all['retcode'])
        ret['comment'] = 'Command "{0}" run'.format(name)
        os.setegid(pgid)
        return ret
    ret['result'] = None
    ret['comment'] = 'Command "{0}" would have been executed'.format(name)
    return ret
Example #33
0
File: cmd.py Project: virHappy/salt
def call(name,
         func,
         args=(),
         kws=None,
         onlyif=None,
         unless=None,
         creates=None,
         output_loglevel='debug',
         use_vt=False,
         **kwargs):
    '''
    Invoke a pre-defined Python function with arguments specified in the state
    declaration. This function is mainly used by the
    :mod:`salt.renderers.pydsl` renderer.

    The interpretation of ``onlyif`` and ``unless`` arguments are identical to
    those of :mod:`cmd.run <salt.states.cmd.run>`, and all other
    arguments(``cwd``, ``runas``, ...) allowed by :mod:`cmd.run
    <salt.states.cmd.run>` are allowed here, except that their effects apply
    only to the commands specified in `onlyif` and `unless` rather than to the
    function to be invoked.

    In addition, the ``stateful`` argument has no effects here.

    The return value of the invoked function will be interpreted as follows.

    If it's a dictionary then it will be passed through to the state system,
    which expects it to have the usual structure returned by any salt state
    function.

    Otherwise, the return value (denoted as ``result`` in the code below) is
    expected to be a JSON serializable object, and this dictionary is returned:

    .. code-block:: python

        {
            'name': name
            'changes': {'retval': result},
            'result': True if result is None else bool(result),
            'comment': result if isinstance(result, string_types) else ''
        }
    '''
    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    cmd_kwargs = {
        'cwd': kwargs.get('cwd'),
        'runas': kwargs.get('user'),
        'shell': kwargs.get('shell') or __grains__['shell'],
        'env': kwargs.get('env'),
        'use_vt': use_vt,
        'output_loglevel': output_loglevel,
        'umask': kwargs.get('umask')
    }
    if HAS_GRP:
        pgid = os.getegid()
    try:
        cret = mod_run_check(cmd_kwargs, onlyif, unless, None, creates)
        if isinstance(cret, dict):
            ret.update(cret)
            return ret
    finally:
        if HAS_GRP:
            os.setegid(pgid)
    if not kws:
        kws = {}
    result = func(*args, **kws)
    if isinstance(result, dict):
        ret.update(result)
        return ret
    else:
        # result must be JSON serializable else we get an error
        ret['changes'] = {'retval': result}
        ret['result'] = True if result is None else bool(result)
        if isinstance(result, string_types):
            ret['comment'] = result
        return ret
Example #34
0
# get pid
assert isinstance(os.getpid(), int)

# unix
if "win" not in sys.platform:
    assert isinstance(os.getegid(), int)
    assert isinstance(os.getgid(), int)
    assert isinstance(os.getsid(os.getpid()), int)
    assert isinstance(os.getuid(), int)
    assert isinstance(os.geteuid(), int)
    assert isinstance(os.getppid(), int)
    assert isinstance(os.getpgid(os.getpid()), int)

    if os.getuid() != 0:
        assert_raises(PermissionError, lambda: os.setgid(42))
        assert_raises(PermissionError, lambda: os.setegid(42))
        assert_raises(PermissionError, lambda: os.setpgid(os.getpid(), 42))
        assert_raises(PermissionError, lambda: os.setuid(42))
        assert_raises(PermissionError, lambda: os.seteuid(42))
        assert_raises(PermissionError, lambda: os.setreuid(42, 42))
        assert_raises(PermissionError, lambda: os.setresuid(42, 42, 42))

    # pty
    a, b = os.openpty()
    assert isinstance(a, int)
    assert isinstance(b, int)
    assert isinstance(os.ttyname(b), str)
    assert_raises(OSError, lambda: os.ttyname(9999))
    os.close(b)
    os.close(a)
def seteuser(user):
    os.setegid(user.pw_gid)
    os.seteuid(user.pw_uid)
Example #36
0
def script(name,
           source=None,
           template=None,
           onlyif=None,
           unless=None,
           cwd='/root',
           user=None,
           group=None,
           shell=None,
           env=None,
           stateful=False,
           **kwargs):
    '''
    Download a script from a remote source and execute it. The name can be the
    source or the source value can be defined.
    source
        The source script being downloaded to the minion, this source script is
        hosted on the salt master server.  If the file is located on the master 
        in the directory named spam, and is called eggs, the source string is 
        salt://spam/eggs
    
    template
        If this setting is applied then the named templating engine will be
        used to render the downloaded file, currently jinja, mako, and wempy
        are supported
    
    name
        The command to execute, remember that the command will execute with the
        path and permissions of the salt-minion.

    onlyif
        A command to run as a check, run the named command only if the command
        passed to the ``onlyif`` option returns true

    unless
        A command to run as a check, only run the named command if the command
        passed to the ``unless`` option returns false

    cwd
        The current working directory to execute the command in, defaults to
        /root

    user
        The user name to run the command as

    group
        The group context to run the command as

    shell
        The shell to use for execution, defaults to the shell grain
    
    env
        The root directory of the environment for the referencing script. The
        environments are defined in the master config file.
    
    stateful
        The command being executed is expected to return data about executing
        a state
    '''
    ret = {'changes': {}, 'comment': '', 'name': name, 'result': False}

    if not os.path.isdir(cwd):
        ret['comment'] = 'Desired working directory is not available'
        return ret

    if env is None:
        env = kwargs.get('__env__', 'base')

    pgid = os.getegid()

    cmd_kwargs = copy.deepcopy(kwargs)
    cmd_kwargs.update({
        'runas': user,
        'shell': shell or __grains__['shell'],
        'env': env,
        'onlyif': onlyif,
        'unless': unless,
        'user': user,
        'group': group,
        'cwd': cwd,
        'template': template
    })

    run_check_cmd_kwargs = {
        'cwd': cwd,
        'runas': user,
        'shell': shell or __grains__['shell'],
    }

    # Change the source to be the name arg if it is not specified
    if source is None:
        source = name

    try:
        cret = _run_check(run_check_cmd_kwargs, onlyif, unless, cwd, user,
                          group, shell)
        if isinstance(cret, dict):
            ret.update(cret)
            return ret

        if __opts__['test']:
            ret['result'] = None
            ret['comment'] = 'Command "{0}" would have been executed'
            ret['comment'] = ret['comment'].format(name)
            return _reinterpreted_state(ret) if stateful else ret

        # Wow, we passed the test, run this sucker!
        try:
            cmd_all = __salt__['cmd.script'](source, **cmd_kwargs)
        except CommandExecutionError as e:
            ret['comment'] = str(e)
            return ret

        ret['changes'] = cmd_all
        if kwargs.get('retcode', False):
            ret['result'] = not bool(cmd_all)
        else:
            ret['result'] = not bool(cmd_all['retcode'])
        ret['comment'] = 'Command "{0}" run'.format(name)
        return _reinterpreted_state(ret) if stateful else ret

    finally:
        os.setegid(pgid)
Example #37
0
def run(name,
        onlyif=None,
        unless=None,
        cwd='/root',
        user=None,
        group=None,
        shell=None,
        env=(),
        stateful=False,
        **kwargs):
    '''
    Run a command if certain circumstances are met

    name
        The command to execute, remember that the command will execute with the
        path and permissions of the salt-minion.

    onlyif
        A command to run as a check, run the named command only if the command
        passed to the ``onlyif`` option returns true

    unless
        A command to run as a check, only run the named command if the command
        passed to the ``unless`` option returns false

    cwd
        The current working directory to execute the command in, defaults to
        /root

    user
        The user name to run the command as

    group
        The group context to run the command as

    shell
        The shell to use for execution, defaults to the shell grain
    
    env
        The root directory of the environment for the referencing script. The
        environments are defined in the master config file.

    stateful
        The command being executed is expected to return data about executing
        a state
    '''
    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    if not os.path.isdir(cwd):
        ret['comment'] = 'Desired working directory is not available'
        return ret

    if env:
        _env = {}
        for var in env.split():
            try:
                k, v = var.split('=')
                _env[k] = v
            except ValueError:
                ret['comment'] = 'Invalid enviromental var: "{0}"'.format(var)
                return ret
        env = _env

    pgid = os.getegid()

    cmd_kwargs = {
        'cwd': cwd,
        'runas': user,
        'shell': shell or __grains__['shell'],
        'env': env
    }

    try:
        cret = _run_check(cmd_kwargs, onlyif, unless, cwd, user, group, shell)
        if isinstance(cret, dict):
            ret.update(cret)
            return ret

        # Wow, we passed the test, run this sucker!
        if not __opts__['test']:
            try:
                cmd_all = __salt__['cmd.run_all'](name, **cmd_kwargs)
            except CommandExecutionError as e:
                ret['comment'] = str(e)
                return ret

            ret['changes'] = cmd_all
            ret['result'] = not bool(cmd_all['retcode'])
            ret['comment'] = 'Command "{0}" run'.format(name)
            return _reinterpreted_state(ret) if stateful else ret
        ret['result'] = None
        ret['comment'] = 'Command "{0}" would have been executed'.format(name)
        return _reinterpreted_state(ret) if stateful else ret

    finally:
        os.setegid(pgid)
Example #38
0
 def end(self, user):
     os.umask(0o022)
     os.seteuid(0)
     os.setegid(0)
     os.setgroups(self.get_groups("root"))
Example #39
0
File: cmd.py Project: virHappy/salt
def run(name,
        onlyif=None,
        unless=None,
        creates=None,
        cwd=None,
        user=None,
        group=None,
        shell=None,
        env=None,
        stateful=False,
        umask=None,
        output_loglevel='debug',
        quiet=False,
        timeout=None,
        use_vt=False,
        **kwargs):
    '''
    Run a command if certain circumstances are met.  Use ``cmd.wait`` if you
    want to use the ``watch`` requisite.

    name
        The command to execute, remember that the command will execute with the
        path and permissions of the salt-minion.

    onlyif
        A command to run as a check, run the named command only if the command
        passed to the ``onlyif`` option returns true

    unless
        A command to run as a check, only run the named command if the command
        passed to the ``unless`` option returns false

    cwd
        The current working directory to execute the command in, defaults to
        /root

    user
        The user name to run the command as

    group
        The group context to run the command as

    shell
        The shell to use for execution, defaults to the shell grain

    env
        A list of environment variables to be set prior to execution.
        Example:

        .. code-block:: yaml

            salt://scripts/foo.sh:
              cmd.script:
                - env:
                  - BATCH: 'yes'

        .. warning::

            The above illustrates a common PyYAML pitfall, that **yes**,
            **no**, **on**, **off**, **true**, and **false** are all loaded as
            boolean ``True`` and ``False`` values, and must be enclosed in
            quotes to be used as strings. More info on this (and other) PyYAML
            idiosyncrasies can be found :doc:`here
            </topics/troubleshooting/yaml_idiosyncrasies>`.

    stateful
        The command being executed is expected to return data about executing
        a state

    umask
        The umask (in octal) to use when running the command.

    output_loglevel
        Control the loglevel at which the output from the command is logged.
        Note that the command being run will still be logged (loglevel: DEBUG)
        regardless, unless ``quiet`` is used for this value.

    quiet
        The command will be executed quietly, meaning no log entries of the
        actual command or its return data. This is deprecated as of the
        **2014.1.0** release, and is being replaced with
        ``output_loglevel: quiet``.

    timeout
        If the command has not terminated after timeout seconds, send the
        subprocess sigterm, and if sigterm is ignored, follow up with sigkill

    creates
        Only run if the file specified by ``creates`` does not exist.

        .. versionadded:: 2014.7.0

    use_vt
        Use VT utils (saltstack) to stream the command output more
        interactively to the console and the logs.
        This is experimental.

    .. note::

        cmd.run supports the usage of ``reload_modules``. This functionality
        allows you to force Salt to reload all modules. You should only use
        ``reload_modules`` if your cmd.run does some sort of installation
        (such as ``pip``), if you do not reload the modules future items in
        your state which rely on the software being installed will fail.

        .. code-block:: yaml

            getpip:
              cmd.run:
                - name: /usr/bin/python /usr/local/sbin/get-pip.py
                - unless: which pip
                - require:
                  - pkg: python
                  - file: /usr/local/sbin/get-pip.py
                - reload_modules: True

    '''
    ### NOTE: The keyword arguments in **kwargs are ignored in this state, but
    ###       cannot be removed from the function definition, otherwise the use
    ###       of unsupported arguments in a cmd.run state will result in a
    ###       traceback.

    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    if cwd and not os.path.isdir(cwd):
        ret['comment'] = ('Desired working directory "{0}" '
                          'is not available').format(cwd)
        return ret

    # Need the check for None here, if env is not provided then it falls back
    # to None and it is assumed that the environment is not being overridden.
    if env is not None and not isinstance(env, (list, dict)):
        ret['comment'] = ('Invalidly-formatted \'env\' parameter. See '
                          'documentation.')
        return ret

    if HAS_GRP:
        pgid = os.getegid()

    cmd_kwargs = {
        'cwd': cwd,
        'runas': user,
        'use_vt': use_vt,
        'shell': shell or __grains__['shell'],
        'env': env,
        'umask': umask,
        'output_loglevel': output_loglevel,
        'quiet': quiet
    }

    try:
        cret = mod_run_check(cmd_kwargs, onlyif, unless, group, creates)
        if isinstance(cret, dict):
            ret.update(cret)
            return ret

        # Wow, we passed the test, run this sucker!
        if not __opts__['test']:
            try:
                cmd_all = __salt__['cmd.run_all'](name,
                                                  timeout=timeout,
                                                  **cmd_kwargs)
            except CommandExecutionError as err:
                ret['comment'] = str(err)
                return ret

            ret['changes'] = cmd_all
            ret['result'] = not bool(cmd_all['retcode'])
            ret['comment'] = 'Command "{0}" run'.format(name)
            return _reinterpreted_state(ret) if stateful else ret
        ret['result'] = None
        ret['comment'] = 'Command "{0}" would have been executed'.format(name)
        return _reinterpreted_state(ret) if stateful else ret

    finally:
        if HAS_GRP:
            os.setegid(pgid)
Example #40
0
File: cmd.py Project: virHappy/salt
def script(name,
           source=None,
           template=None,
           onlyif=None,
           unless=None,
           creates=None,
           cwd=None,
           user=None,
           group=None,
           shell=None,
           env=None,
           stateful=False,
           umask=None,
           timeout=None,
           use_vt=False,
           output_loglevel='debug',
           **kwargs):
    '''
    Download a script and execute it with specified arguments.

    source
        The location of the script to download. If the file is located on the
        master in the directory named spam, and is called eggs, the source
        string is salt://spam/eggs

    template
        If this setting is applied then the named templating engine will be
        used to render the downloaded file. Currently jinja, mako, and wempy
        are supported

    name
        Either "cmd arg1 arg2 arg3..." (cmd is not used) or a source
        "salt://...".

    onlyif
        Run the named command only if the command passed to the ``onlyif``
        option returns true

    unless
        Run the named command only if the command passed to the ``unless``
        option returns false

    cwd
        The current working directory to execute the command in, defaults to
        /root

    user
        The name of the user to run the command as

    group
        The group context to run the command as

    shell
        The shell to use for execution. The default is set in grains['shell']

    env
        A list of environment variables to be set prior to execution.
        Example:

        .. code-block:: yaml

            salt://scripts/foo.sh:
              cmd.script:
                - env:
                  - BATCH: 'yes'

        .. warning::

            The above illustrates a common PyYAML pitfall, that **yes**,
            **no**, **on**, **off**, **true**, and **false** are all loaded as
            boolean ``True`` and ``False`` values, and must be enclosed in
            quotes to be used as strings. More info on this (and other) PyYAML
            idiosyncrasies can be found :doc:`here
            </topics/troubleshooting/yaml_idiosyncrasies>`.

    umask
         The umask (in octal) to use when running the command.

    stateful
        The command being executed is expected to return data about executing
        a state

    timeout
        If the command has not terminated after timeout seconds, send the
        subprocess sigterm, and if sigterm is ignored, follow up with sigkill

    args
        String of command line args to pass to the script.  Only used if no
        args are specified as part of the `name` argument. To pass a string
        containing spaces in YAML, you will need to doubly-quote it:  "arg1
        'arg two' arg3"

    creates
        Only run if the file specified by ``creates`` does not exist.

        .. versionadded:: 2014.7.0

    use_vt
        Use VT utils (saltstack) to stream the command output more
        interactively to the console and the logs.
        This is experimental.

    output_loglevel
        Control the loglevel at which the output from the command is logged.
        Note that the command being run will still be logged (loglevel: DEBUG)
        regardless, unless ``quiet`` is used for this value.

    '''
    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    if cwd and not os.path.isdir(cwd):
        ret['comment'] = ('Desired working directory "{0}" '
                          'is not available').format(cwd)
        return ret

    # Need the check for None here, if env is not provided then it falls back
    # to None and it is assumed that the environment is not being overridden.
    if env is not None and not isinstance(env, (list, dict)):
        ret['comment'] = ('Invalidly-formatted \'env\' parameter. See '
                          'documentation.')
        return ret

    if HAS_GRP:
        pgid = os.getegid()

    cmd_kwargs = copy.deepcopy(kwargs)
    cmd_kwargs.update({
        'runas': user,
        'shell': shell or __grains__['shell'],
        'env': env,
        'onlyif': onlyif,
        'unless': unless,
        'user': user,
        'group': group,
        'cwd': cwd,
        'template': template,
        'umask': umask,
        'timeout': timeout,
        'output_loglevel': output_loglevel,
        'use_vt': use_vt,
        'saltenv': __env__
    })

    run_check_cmd_kwargs = {
        'cwd': cwd,
        'runas': user,
        'shell': shell or __grains__['shell']
    }

    # Change the source to be the name arg if it is not specified
    if source is None:
        source = name

    # If script args present split from name and define args
    if len(name.split()) > 1:
        cmd_kwargs.update({'args': name.split(' ', 1)[1]})

    try:
        cret = mod_run_check(run_check_cmd_kwargs, onlyif, unless, group,
                             creates)
        if isinstance(cret, dict):
            ret.update(cret)
            return ret

        if __opts__['test']:
            ret['result'] = None
            ret['comment'] = 'Command {0!r} would have been ' \
                             'executed'.format(name)
            return _reinterpreted_state(ret) if stateful else ret

        # Wow, we passed the test, run this sucker!
        try:
            cmd_all = __salt__['cmd.script'](source, **cmd_kwargs)
        except (CommandExecutionError, SaltRenderError, IOError) as err:
            ret['comment'] = str(err)
            return ret

        ret['changes'] = cmd_all
        if kwargs.get('retcode', False):
            ret['result'] = not bool(cmd_all)
        else:
            ret['result'] = not bool(cmd_all['retcode'])
        if ret.get('changes', {}).get('cache_error'):
            ret['comment'] = 'Unable to cache script {0} from saltenv ' \
                             '{1!r}'.format(source, __env__)
        else:
            ret['comment'] = 'Command {0!r} run'.format(name)
        return _reinterpreted_state(ret) if stateful else ret

    finally:
        if HAS_GRP:
            os.setegid(pgid)
Example #41
0
 def preexec():
     if resource.group:
         gid = grp.getgrnam(resource.group).gr_gid
         os.setgid(gid)
         os.setegid(gid)
Example #42
0
File: cmd.py Project: virHappy/salt
def mod_run_check(cmd_kwargs, onlyif, unless, group, creates):
    '''
    Execute the onlyif and unless logic.
    Return a result dict if:
    * group is not available
    * onlyif failed (onlyif != 0)
    * unless succeeded (unless == 0)
    else return True
    '''
    # never use VT for onlyif/unless executions because this will lead
    # to quote problems
    cmd_kwargs = copy.deepcopy(cmd_kwargs)
    cmd_kwargs['use_vt'] = False
    if group and HAS_GRP:
        try:
            egid = grp.getgrnam(group).gr_gid
            if not __opts__['test']:
                os.setegid(egid)
        except KeyError:
            return {
                'comment': 'The group {0} is not available'.format(group),
                'result': False
            }

    if onlyif is not None:
        if isinstance(onlyif, string_types):
            cmd = __salt__['cmd.retcode'](onlyif,
                                          ignore_retcode=True,
                                          **cmd_kwargs)
            log.debug('Last command return code: {0}'.format(cmd))
            if cmd != 0:
                return {
                    'comment': 'onlyif execution failed',
                    'skip_watch': True,
                    'result': True
                }
        elif isinstance(onlyif, list):
            for entry in onlyif:
                cmd = __salt__['cmd.retcode'](entry,
                                              ignore_retcode=True,
                                              **cmd_kwargs)
                log.debug('Last command return code: {0}'.format(cmd))
                if cmd != 0:
                    return {
                        'comment': 'onlyif execution failed',
                        'skip_watch': True,
                        'result': True
                    }
        elif not isinstance(onlyif, string_types):
            if not onlyif:
                log.debug(
                    'Command not run: onlyif did not evaluate to string_type')
                return {
                    'comment': 'onlyif execution failed',
                    'skip_watch': True,
                    'result': True
                }

    if unless is not None:
        if isinstance(unless, string_types):
            cmd = __salt__['cmd.retcode'](unless,
                                          ignore_retcode=True,
                                          **cmd_kwargs)
            log.debug('Last command return code: {0}'.format(cmd))
            if cmd == 0:
                return {
                    'comment': 'unless execution succeeded',
                    'skip_watch': True,
                    'result': True
                }
        elif isinstance(unless, list):
            for entry in unless:
                cmd = __salt__['cmd.retcode'](entry,
                                              ignore_retcode=True,
                                              **cmd_kwargs)
                log.debug('Last command return code: {0}'.format(cmd))
                if cmd == 0:
                    return {
                        'comment': 'unless execution succeeded',
                        'skip_watch': True,
                        'result': True
                    }
        elif not isinstance(unless, string_types):
            if unless:
                log.debug(
                    'Command not run: unless did not evaluate to string_type')
                return {
                    'comment': 'unless execution succeeded',
                    'skip_watch': True,
                    'result': True
                }

    if isinstance(creates, string_types) and os.path.exists(creates):
        return {'comment': '{0} exists'.format(creates), 'result': True}
    elif isinstance(creates, list) and all(
        [os.path.exists(path) for path in creates]):
        return {'comment': 'All files in creates exist', 'result': True}

    # No reason to stop, return True
    return True
Example #43
0
def become_root():
    os.seteuid(0)
    os.setegid(0)
Example #44
0
 def preexec():
     if resource.group:
         gid = _coerce_gid(resource.group)
         os.setgid(gid)
         os.setegid(gid)
Example #45
0
 def become_unprivileged_user(cls):
     try:
         os.setegid(cls._gid_of_user_invoking_sudo)
         os.seteuid(cls._uid_of_user_invoking_sudo)
     except AttributeError:
         pass
Example #46
0
def become_user(uid, gid):
    os.setegid(gid)
    os.seteuid(uid)
Example #47
0
def send(cmd):
    gpio.output(cmd, gpio.LOW)
    time.sleep(.3)
    gpio.output(cmd, gpio.HIGH)


@atexit.register
def cleanup():
    try:
        os.unlink(FIFO)
    except:
        pass


os.setegid(116)
os.umask(0000)


def main():
    os.mkfifo(FIFO)
    while True:
        with open(FIFO) as fifo:
            line = fifo.readline().rstrip()
            print repr(line)
            if line == "u":
                send(up)
            elif line == "d":
                send(down)
            elif line == "q":
                exit()
Example #48
0
def setegid(gid):
    """Set effective group id."""
    gid = parse_gid(gid)
    if gid != os.getegid():
        os.setegid(gid)
Example #49
0
 def __enter__(self):
     os.setegid(int(self.user.gid))
     os.seteuid(int(self.user.uid))
     IO.write("ID changed : %s" % (os.getresuid(), ))
     return self
Example #50
0
 def become_privileged_user(cls):
     try:
         os.setegid(cls._root_user_gid)
         os.seteuid(cls._root_user_uid)
     except AttributeError:
         pass
    def restore_privs(self):

        os.seteuid(self.orig_uid)
        os.setegid(self.orig_gid)
        os.setgroups(self.orig_groups)
Example #52
0
 def __exit__(self, typ, val, tb):
     os.seteuid(0)
     os.setegid(0)
     IO.write("ID changed : %s" % (os.getresuid(), ))
Example #53
0
def raise_privileges():
    if is_root():
        return

    os.setegid(0)
    os.seteuid(0)
Example #54
0
def run_as_nobody():
    """Runs the current process as nobody."""
    # Set the effective uid and to that of nobody.
    nobody = pwd.getpwnam('nobody')
    os.setegid(nobody.pw_gid)
    os.seteuid(nobody.pw_uid)
Example #55
0
 def dropPriviledge():
     assert os.geteuid() == 0 and os.getegid() == 0
     os.setegid(os.getresgid()[2])
     os.seteuid(os.getresuid()[2])
Example #56
0
    def _run_one(self, path, args, queue=None):
        # Set the uid of the process
        os.seteuid(0)
        os.setegid(0)

        if queue is None:
            pwnam = pwd.getpwnam(self.read_user)
        else:
            pwnam = pwd.getpwnam(self.full_user)

        os.setgid(pwnam.pw_gid)
        os.setuid(pwnam.pw_uid)

        # Redirect STDOUT and STDERR to file, close STDIN
        stdout = sys.stdout
        stderr = sys.stderr
        sys.stdout = open(path + '/_stdout', 'a')
        sys.stderr = open(path + '/_stderr', 'a')
        sys.stdin.close()

        ## Ignore SIGINT - see note above proc.terminate()
        ## We will react to SIGTERM by raising KeyboardInterrupt
        import signal
        from dynamo.utils.signaling import SignalConverter

        signal.signal(signal.SIGINT, signal.SIG_IGN)

        signal_converter = SignalConverter()
        signal_converter.set(signal.SIGTERM)

        # Set argv
        sys.argv = [path + '/exec.py']
        if args:
            sys.argv += args.split()

        # Reset logging
        # This is a rather hacky solution relying perhaps on the implementation internals of
        # the logging module. It might stop working with changes to the logging.
        # The assumptions are:
        #  1. All loggers can be reached through Logger.manager.loggerDict
        #  2. All logging.shutdown() does is call flush() and close() over all handlers
        #     (i.e. calling the two is enough to ensure clean cutoff from all resources)
        #  3. root_logger.handlers is the only link the root logger has to its handlers
        for logger in [logging.getLogger()
                       ] + logging.Logger.manager.loggerDict.values():
            while True:
                try:
                    handler = logger.handlers.pop()
                except AttributeError:
                    # logger is just a PlaceHolder and does not have .handlers
                    break
                except IndexError:
                    break

                handler.flush()
                handler.close()

        # Re-initialize
        #  - inventory store with read-only connection
        #  - registry backend with read-only connection
        # This is for security and simply for concurrency - multiple processes
        # should not share the same DB connection
        backend_config = self.registry_config.backend
        self.registry.set_backend(backend_config.interface,
                                  backend_config.readonly_config)

        persistency_config = self.inventory_config.persistency
        self.inventory.init_store(persistency_config.module,
                                  persistency_config.readonly_config)

        # Pass my registry and inventory to the executable through core.executable
        import dynamo.core.executable as executable
        executable.registry = self.registry
        executable.inventory = self.inventory

        if queue is not None:
            executable.read_only = False
            # create a list of updated objects the executable can fill
            executable.inventory._updated_objects = []
            executable.inventory._deleted_objects = []

        execfile(path + '/exec.py')

        if queue is not None:
            for obj in self.inventory._updated_objects:
                try:
                    queue.put((Dynamo.CMD_UPDATE, obj))
                except:
                    sys.stderr.write('Exception while sending updated %s\n' %
                                     str(obj))
                    raise

            for obj in self.inventory._deleted_objects:
                try:
                    queue.put((Dynamo.CMD_DELETE, obj))
                except:
                    sys.stderr.write('Exception while sending updated %s\n' %
                                     str(obj))
                    raise

            # Put end-of-message
            queue.put((Dynamo.CMD_EOM, None))

        # Queue stays available on the other end even if we terminate the process

        sys.stdout.close()
        sys.stderr.close()
        sys.stdout = stdout
        sys.stderr = stderr
Example #57
0
def unzip(zip_file,
          dest,
          excludes=None,
          options=None,
          template=None,
          runas=None,
          trim_output=False,
          password=None,
          extract_perms=True):
    '''
    Uses the ``zipfile`` Python module to unpack zip files

    .. versionchanged:: 2015.5.0
        This function was rewritten to use Python's native zip file support.
        The old functionality has been preserved in the new function
        :mod:`archive.cmd_unzip <salt.modules.archive.cmd_unzip>`. For versions
        2014.7.x and earlier, see the :mod:`archive.cmd_zip
        <salt.modules.archive.cmd_zip>` documentation.

    zip_file
        Path of zip file to be unpacked

    dest
        The destination directory into which the file should be unpacked

    excludes : None
        Comma-separated list of files not to unpack. Can also be passed in a
        Python list.

    options
        This options are only used when ``unzip`` binary is used. In this
        function is ignored.

        .. versionadded:: 2016.3.1

    template : None
        Can be set to 'jinja' or another supported template engine to render
        the command arguments before execution:

        .. code-block:: bash

            salt '*' archive.unzip template=jinja /tmp/zipfile.zip /tmp/{{grains.id}}/ excludes=file_1,file_2

    runas : None
        Unpack the zip file as the specified user. Defaults to the user under
        which the minion is running.

    trim_output : False
        The number of files we should output on success before the rest are trimmed, if this is
        set to True then it will default to 100

    CLI Example:

    .. code-block:: bash

        salt '*' archive.unzip /tmp/zipfile.zip /home/strongbad/ excludes=file_1,file_2

    password
        Password to use with password protected zip files

        .. note::
            The password will be present in the events logged to the minion log
            file at the ``debug`` log level. If the minion is logging at
            ``debug`` (or more verbose), then be advised that the password will
            appear in the log.

        .. versionadded:: 2016.3.0

    extract_perms : True
        The Python zipfile_ module does not extract file/directory attributes
        by default. When this argument is set to ``True``, Salt will attempt to
        apply the file permission attributes to the extracted files/folders.

        On Windows, only the read-only flag will be extracted as set within the
        zip file, other attributes (i.e. user/group permissions) are ignored.

        Set this argument to ``False`` to disable this behavior.

        .. versionadded:: 2016.11.0

    .. _zipfile: https://docs.python.org/2/library/zipfile.html

    CLI Example:

    .. code-block:: bash

        salt '*' archive.unzip /tmp/zipfile.zip /home/strongbad/ password='******'
    '''
    if not excludes:
        excludes = []
    if runas:
        euid = os.geteuid()
        egid = os.getegid()
        uinfo = __salt__['user.info'](runas)
        if not uinfo:
            raise SaltInvocationError(
                "User '{0}' does not exist".format(runas))

    zip_file, dest = _render_filenames(zip_file, dest, None, template)

    if runas and (euid != uinfo['uid'] or egid != uinfo['gid']):
        # Change the egid first, as changing it after the euid will fail
        # if the runas user is non-privileged.
        os.setegid(uinfo['gid'])
        os.seteuid(uinfo['uid'])

    try:
        # Define cleaned_files here so that an exception will not prevent this
        # variable from being defined and cause a NameError in the return
        # statement at the end of the function.
        cleaned_files = []
        with contextlib.closing(zipfile.ZipFile(zip_file, "r")) as zfile:
            files = zfile.namelist()

            if isinstance(excludes, six.string_types):
                excludes = [x.strip() for x in excludes.split(',')]
            elif isinstance(excludes, (float, six.integer_types)):
                excludes = [six.text_type(excludes)]

            cleaned_files.extend([x for x in files if x not in excludes])
            for target in cleaned_files:
                if target not in excludes:
                    if salt.utils.platform.is_windows() is False:
                        info = zfile.getinfo(target)
                        # Check if zipped file is a symbolic link
                        if stat.S_ISLNK(info.external_attr >> 16):
                            source = zfile.read(target)
                            os.symlink(source, os.path.join(dest, target))
                            continue
                    zfile.extract(target, dest, password)
                    if extract_perms:
                        if not salt.utils.platform.is_windows():
                            perm = zfile.getinfo(target).external_attr >> 16
                            if perm == 0:
                                umask_ = salt.utils.files.get_umask()
                                if target.endswith('/'):
                                    perm = 0o777 & ~umask_
                                else:
                                    perm = 0o666 & ~umask_
                            os.chmod(os.path.join(dest, target), perm)
                        else:
                            win32_attr = zfile.getinfo(
                                target).external_attr & 0xFF
                            win32file.SetFileAttributes(
                                os.path.join(dest, target), win32_attr)
    except Exception as exc:
        if runas:
            os.seteuid(euid)
            os.setegid(egid)
        # Wait to raise the exception until euid/egid are restored to avoid
        # permission errors in writing to minion log.
        raise CommandExecutionError(
            'Exception encountered unpacking zipfile: {0}'.format(exc))
    finally:
        # Restore the euid/egid
        if runas:
            os.seteuid(euid)
            os.setegid(egid)

    return _trim_files(cleaned_files, trim_output)
Example #58
0
def my_pre_exec():
    os.setegid(1000)
    os.seteuid(1000)
Example #59
0
def zip_(zip_file, sources, template=None, cwd=None, runas=None):
    '''
    Uses the ``zipfile`` Python module to create zip files

    .. versionchanged:: 2015.5.0
        This function was rewritten to use Python's native zip file support.
        The old functionality has been preserved in the new function
        :mod:`archive.cmd_zip <salt.modules.archive.cmd_zip>`. For versions
        2014.7.x and earlier, see the :mod:`archive.cmd_zip
        <salt.modules.archive.cmd_zip>` documentation.

    zip_file
        Path of zip file to be created

    sources
        Comma-separated list of sources to include in the zip file. Sources can
        also be passed in a Python list.

        .. versionchanged:: 2017.7.0
            Globbing is now supported for this argument

    template : None
        Can be set to 'jinja' or another supported template engine to render
        the command arguments before execution:

        .. code-block:: bash

            salt '*' archive.zip template=jinja /tmp/zipfile.zip /tmp/sourcefile1,/tmp/{{grains.id}}.txt

    cwd : None
        Use this argument along with relative paths in ``sources`` to create
        zip files which do not contain the leading directories. If not
        specified, the zip file will be created as if the cwd was ``/``, and
        creating a zip file of ``/foo/bar/baz.txt`` will contain the parent
        directories ``foo`` and ``bar``. To create a zip file containing just
        ``baz.txt``, the following command would be used:

        .. code-block:: bash

            salt '*' archive.zip /tmp/baz.zip baz.txt cwd=/foo/bar

    runas : None
        Create the zip file as the specified user. Defaults to the user under
        which the minion is running.


    CLI Example:

    .. code-block:: bash

        salt '*' archive.zip /tmp/zipfile.zip /tmp/sourcefile1,/tmp/sourcefile2
        # Globbing for sources (2017.7.0 and later)
        salt '*' archive.zip /tmp/zipfile.zip '/tmp/sourcefile*'
    '''
    if runas:
        euid = os.geteuid()
        egid = os.getegid()
        uinfo = __salt__['user.info'](runas)
        if not uinfo:
            raise SaltInvocationError(
                'User \'{0}\' does not exist'.format(runas))

    zip_file, sources = _render_filenames(zip_file, sources, None, template)
    sources = _expand_sources(sources)

    if not cwd:
        for src in sources:
            if not os.path.isabs(src):
                raise SaltInvocationError(
                    'Relative paths require the \'cwd\' parameter')
    else:
        err_msg = 'cwd must be absolute'
        try:
            if not os.path.isabs(cwd):
                raise SaltInvocationError(err_msg)
        except AttributeError:
            raise SaltInvocationError(err_msg)

    if runas and (euid != uinfo['uid'] or egid != uinfo['gid']):
        # Change the egid first, as changing it after the euid will fail
        # if the runas user is non-privileged.
        os.setegid(uinfo['gid'])
        os.seteuid(uinfo['uid'])

    try:
        exc = None
        archived_files = []
        with contextlib.closing(
                zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)) as zfile:
            for src in sources:
                if cwd:
                    src = os.path.join(cwd, src)
                if os.path.exists(src):
                    if os.path.isabs(src):
                        rel_root = '/'
                    else:
                        rel_root = cwd if cwd is not None else '/'
                    if os.path.isdir(src):
                        for dir_name, sub_dirs, files in salt.utils.path.os_walk(
                                src):
                            if cwd and dir_name.startswith(cwd):
                                arc_dir = os.path.relpath(dir_name, cwd)
                            else:
                                arc_dir = os.path.relpath(dir_name, rel_root)
                            if arc_dir:
                                archived_files.append(arc_dir + '/')
                                zfile.write(dir_name, arc_dir)
                            for filename in files:
                                abs_name = os.path.join(dir_name, filename)
                                arc_name = os.path.join(arc_dir, filename)
                                archived_files.append(arc_name)
                                zfile.write(abs_name, arc_name)
                    else:
                        if cwd and src.startswith(cwd):
                            arc_name = os.path.relpath(src, cwd)
                        else:
                            arc_name = os.path.relpath(src, rel_root)
                        archived_files.append(arc_name)
                        zfile.write(src, arc_name)
    except Exception as exc:
        pass
    finally:
        # Restore the euid/egid
        if runas:
            os.seteuid(euid)
            os.setegid(egid)
        if exc is not None:
            # Wait to raise the exception until euid/egid are restored to avoid
            # permission errors in writing to minion log.
            raise CommandExecutionError(
                'Exception encountered creating zipfile: {0}'.format(exc))

    return archived_files
Example #60
0
 def risePriviledge():
     os.setegid(0)
     os.seteuid(0)