Exemple #1
0
def userdel(name: str) -> None:
    if user_exists(name):
        try:
            p = subprocess.Popen(  # pylint:disable=consider-using-with
                ["userdel", "-r", name],
                stdin=open(os.devnull, "r"),  # pylint:disable=consider-using-with
                stdout=open(os.devnull, "w"),  # pylint:disable=consider-using-with
                stderr=subprocess.PIPE,
                close_fds=True,
                encoding="utf-8",
            )
        except OSError as e:
            raise MKTerminate("\n" + tty.error +
                              ": Failed to delete user '%s': %s" % (name, e))

        stderr = p.communicate()[1]
        if p.returncode != 0:
            raise MKTerminate("\n" + tty.error +
                              ": Failed to delete user '%s': %s" %
                              (name, stderr))

    # On some OSes (e.g. debian) the group is automatically removed if
    # it bears the same name as the user. So first check for the group.
    if group_exists(name):
        groupdel(name)
Exemple #2
0
def user_confirms(site, conflict_mode, title, message, relpath, yes_choice,
                  yes_text, no_choice, no_text):
    # type: (SiteContext, str, str, str, str, str, str, str, str) -> bool
    # Handle non-interactive mode
    if conflict_mode == "abort":
        raise MKTerminate("Update aborted.")
    if conflict_mode == "install":
        return False
    if conflict_mode == "keepold":
        return True

    user_path = site.dir + "/" + relpath
    options = [(yes_choice, yes_text), (no_choice, no_text),
               ("shell", "Open a shell for looking around"),
               ("abort", "Stop here and abort update!")]
    while True:
        choice = ask_user_choices(title, message, options)
        if choice == "abort":
            raise MKTerminate("Update aborted.")

        if choice == "shell":
            thedir = "/".join(user_path.split("/")[:-1])
            sys.stdout.write("\n Starting BASH. Type CTRL-D to continue.\n\n")
            subprocess.Popen(["bash", "-i"], cwd=thedir).wait()
        else:
            return choice == yes_choice
Exemple #3
0
def userdel(name: str) -> None:
    if user_exists(name):
        try:
            completed_process = subprocess.run(
                ["userdel", "-r", name],
                stdin=subprocess.DEVNULL,
                stdout=subprocess.DEVNULL,
                stderr=subprocess.PIPE,
                close_fds=True,
                encoding="utf-8",
                check=False,
            )
        except OSError as e:
            raise MKTerminate("\n" + tty.error +
                              ": Failed to delete user '%s': %s" % (name, e))

        if completed_process.returncode:
            raise MKTerminate("\n" + tty.error +
                              ": Failed to delete user '%s': %s" %
                              (name, completed_process.stderr))

    # On some OSes (e.g. debian) the group is automatically removed if
    # it bears the same name as the user. So first check for the group.
    if group_exists(name):
        groupdel(name)
Exemple #4
0
def _config_load_hook(site: "SiteContext", hook_name: str) -> ConfigHook:
    hook: ConfigHook = {
        "name": hook_name,
        "deprecated": False,
    }

    if not site.hook_dir:
        # IMHO this should be unreachable...
        raise MKTerminate("Site has no version and therefore no hooks")

    description = ""
    description_active = False
    with Path(site.hook_dir, hook_name).open() as hook_file:
        for line in hook_file:
            if line.startswith("# Alias:"):
                hook["alias"] = line[8:].strip()
            elif line.startswith("# Menu:"):
                hook["menu"] = line[7:].strip()
            elif line.startswith("# Deprecated: yes"):
                hook["deprecated"] = True
            elif line.startswith("# Description:"):
                description_active = True
            elif line.startswith("#  ") and description_active:
                description += line[3:].strip() + "\n"
            else:
                description_active = False
    hook["description"] = description

    def get_hook_info(info: str) -> str:
        return call_hook(site, hook_name, [info])[1]

    # The choices can either be a list of possible keys. Then
    # the hook outputs one live for each choice where the key and a
    # description are separated by a colon. Or it outputs one line
    # where that line is an extended regular expression matching the
    # possible values.
    choicestxt = get_hook_info("choices").split("\n")
    choices: ConfigHookChoices = None
    if len(choicestxt) == 1:
        regextext = choicestxt[0].strip()
        if regextext != "":
            choices = re.compile(regextext + "$")
        else:
            choices = None
    else:
        choices = []
        try:
            for line in choicestxt:
                val, descr = line.split(":", 1)
                val = val.strip()
                descr = descr.strip()
                choices.append((val, descr))
        except Exception as e:
            raise MKTerminate("Invalid output of hook: %s: %s" %
                              (choicestxt, e))

    hook["choices"] = choices
    return hook
Exemple #5
0
def groupdel(groupname: str) -> None:
    try:
        p = subprocess.Popen(["groupdel", groupname],
                             stdin=open(os.devnull, "r"),
                             stdout=open(os.devnull, "w"),
                             stderr=subprocess.PIPE,
                             close_fds=True,
                             encoding="utf-8")
    except OSError as e:
        raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, e))

    stderr = p.communicate()[1]
    if p.returncode != 0:
        raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" %
                          (groupname, stderr))
Exemple #6
0
def useradd(
    version_info: "VersionInfo",
    site: "SiteContext",
    uid: Optional[str] = None,
    gid: Optional[str] = None,
) -> None:
    # Create user for running site 'name'
    _groupadd(site.name, gid)
    useradd_options = version_info.USERADD_OPTIONS
    if uid is not None:
        useradd_options += " -u %d" % int(uid)
    if (os.system(  # nosec
            "useradd %s -r -d '%s' -c 'OMD site %s' -g %s -G omd %s -s /bin/bash"
            %
        (useradd_options, site.dir, site.name, site.name, site.name)) != 0):
        groupdel(site.name)
        raise MKTerminate("Error creating site user.")

    # On SLES11+ there is a standard group "trusted" that the OMD site users should be members
    # of to be able to access CRON.
    if group_exists("trusted"):
        _add_user_to_group(version_info, site.name, "trusted")

    # Add Apache to new group. It needs to be able to write in to the
    # command pipe and possible other stuff
    _add_user_to_group(version_info, version_info.APACHE_USER, site.name)
Exemple #7
0
def call_hook(site: "SiteContext", hook_name: str,
              args: List[str]) -> ConfigHookResult:

    if not site.hook_dir:
        # IMHO this should be unreachable...
        raise MKTerminate("Site has no version and therefore no hooks")

    cmd = [site.hook_dir + hook_name] + args
    hook_env = os.environ.copy()
    hook_env.update({
        "OMD_ROOT": site.dir,
        "OMD_SITE": site.name,
    })

    logger.log(VERBOSE, "Calling hook: %s", subprocess.list2cmdline(cmd))

    completed_process = subprocess.run(
        cmd,
        env=hook_env,
        close_fds=True,
        shell=False,
        stdout=subprocess.PIPE,
        encoding="utf-8",
        check=False,
    )
    content = completed_process.stdout.strip()

    if completed_process.returncode and args[0] != "depends":
        sys.stderr.write("Error running %s: %s\n" %
                         (subprocess.list2cmdline(cmd), content))

    return completed_process.returncode, content
Exemple #8
0
    def _handle_sigterm(self, signum: int, frame: Optional[FrameType]) -> None:
        self._logger.debug("Received SIGTERM")
        status = self._jobstatus.get_status_from_file()
        if not status.get("stoppable", True):
            self._logger.warning("Skip termination of background job (Job ID: %s, PID: %d)",
                                 self._job_parameters["job_id"], os.getpid())
            return

        raise MKTerminate()
Exemple #9
0
    def skel_permissions(self) -> Permissions:
        """Returns the skeleton permissions. Load either from version meta directory
        or from the original version skel.permissions file"""
        if not self._has_version_meta_data():
            if self.version is None:
                raise MKTerminate("Failed to determine site version")
            return load_skel_permissions(self.version)

        return load_skel_permissions_from(self.version_meta_dir +
                                          "/skel.permissions")
Exemple #10
0
def groupdel(groupname: str) -> None:
    try:
        completed_process = subprocess.run(
            ["groupdel", groupname],
            stdin=subprocess.DEVNULL,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.PIPE,
            close_fds=True,
            encoding="utf-8",
            check=False,
        )
    except OSError as e:
        raise MKTerminate("\n" + tty.error +
                          ": Failed to delete group '%s': %s" % (groupname, e))

    if completed_process.returncode:
        raise MKTerminate("\n" + tty.error +
                          ": Failed to delete group '%s': %s" %
                          (groupname, completed_process.stderr))
Exemple #11
0
def _groupadd(groupname: str, gid: Optional[str] = None) -> None:
    cmd = ["groupadd"]
    if gid is not None:
        cmd += ["-g", "%d" % int(gid)]
    cmd.append(groupname)
    if subprocess.run(cmd,
                      close_fds=True,
                      stdin=subprocess.DEVNULL,
                      check=False).returncode:
        raise MKTerminate("Cannot create group for site user.")
Exemple #12
0
def groupdel(groupname: str) -> None:
    try:
        p = subprocess.Popen(  # pylint:disable=consider-using-with
            ["groupdel", groupname],
            stdin=subprocess.DEVNULL,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.PIPE,
            close_fds=True,
            encoding="utf-8",
        )
    except OSError as e:
        raise MKTerminate("\n" + tty.error +
                          ": Failed to delete group '%s': %s" % (groupname, e))

    stderr = p.communicate()[1]
    if p.returncode != 0:
        raise MKTerminate("\n" + tty.error +
                          ": Failed to delete group '%s': %s" %
                          (groupname, stderr))
Exemple #13
0
def _config_load_hook(site, hook_name):
    # type: (SiteContext, str) -> ConfigHook
    hook = {
        "name": hook_name,
        "deprecated": False,
    }  # type: ConfigHook

    description = ""
    description_active = False
    for line in open(site.dir + "/lib/omd/hooks/" + hook_name):
        if line.startswith("# Alias:"):
            hook["alias"] = line[8:].strip()
        elif line.startswith("# Menu:"):
            hook["menu"] = line[7:].strip()
        elif line.startswith("# Deprecated: yes"):
            hook["deprecated"] = True
        elif line.startswith("# Description:"):
            description_active = True
        elif line.startswith("#  ") and description_active:
            description += line[3:].strip() + "\n"
        else:
            description_active = False
    hook["description"] = description

    def get_hook_info(info):
        # type: (str) -> str
        return call_hook(site, hook_name, [info])[1]

    # The choices can either be a list of possible keys. Then
    # the hook outputs one live for each choice where the key and a
    # description are separated by a colon. Or it outputs one line
    # where that line is an extended regular expression matching the
    # possible values.
    choicestxt = get_hook_info("choices").split("\n")
    choices = None  # type: ConfigHookChoices
    if len(choicestxt) == 1:
        regextext = choicestxt[0].strip()
        if regextext != "":
            choices = re.compile(regextext + "$")
        else:
            choices = None
    else:
        choices = []
        try:
            for line in choicestxt:
                val, descr = line.split(":", 1)
                val = val.strip()
                descr = descr.strip()
                choices.append((val, descr))
        except Exception as e:
            raise MKTerminate("Invalid output of hook: %s: %s" %
                              (choicestxt, e))

    hook["choices"] = choices
    return hook
Exemple #14
0
def _groupadd(groupname: str, gid: Optional[str] = None) -> None:
    cmd = ["groupadd"]
    if gid is not None:
        cmd += ["-g", "%d" % int(gid)]
    cmd.append(groupname)

    if (subprocess.Popen(  # pylint:disable=consider-using-with
            cmd,
            close_fds=True,
            stdin=open(os.devnull, "r"),  # pylint:disable=consider-using-with
    ).wait() != 0):
        raise MKTerminate("Cannot create group for site user.")
Exemple #15
0
def _groupadd(groupname: str, gid: Optional[str] = None) -> None:
    cmd = ["groupadd"]
    if gid is not None:
        cmd += ["-g", "%d" % int(gid)]
    cmd.append(groupname)

    if subprocess.Popen(
            cmd,
            close_fds=True,
            stdin=open(os.devnull, "r"),
    ).wait() != 0:
        raise MKTerminate("Cannot create group for site user.")
Exemple #16
0
def user_verify(version_info: "VersionInfo",
                site: "SiteContext",
                allow_populated: bool = False) -> bool:
    name = site.name

    if not user_exists(name):
        raise MKTerminate(tty.error + ": user %s does not exist" % name)

    user = _user_by_id(user_id(name))
    if user.pw_dir != site.dir:
        raise MKTerminate(tty.error +
                          ": Wrong home directory for user %s, must be %s" %
                          (name, site.dir))

    if not os.path.exists(site.dir):
        raise MKTerminate(tty.error +
                          ": home directory for user %s (%s) does not exist" %
                          (name, site.dir))

    if not allow_populated and os.path.exists(site.dir + "/version"):
        raise MKTerminate(tty.error +
                          ": home directory for user %s (%s) must be empty" %
                          (name, site.dir))

    if not _file_owner_verify(site.dir, user.pw_uid, user.pw_gid):
        raise MKTerminate(
            tty.error +
            ": home directory (%s) is not owned by user %s and group %s" %
            (site.dir, name, name))

    group = _group_by_id(user.pw_gid)
    if group is None or group.gr_name != name:
        raise MKTerminate(tty.error +
                          ": primary group for siteuser must be %s" % name)

    if not _user_has_group(version_info.APACHE_USER, name):
        raise MKTerminate(tty.error +
                          ": apache user %s must be member of group %s" %
                          (version_info.APACHE_USER, name))

    if not _user_has_group(name, "omd"):
        raise MKTerminate(tty.error + ": siteuser must be member of group omd")

    return True
Exemple #17
0
def _handle_keepalive_interrupt(signum: int,
                                frame: Optional[FrameType]) -> NoReturn:
    raise MKTerminate()
Exemple #18
0
def _handle_keepalive_interrupt(signum, frame):
    raise MKTerminate()
Exemple #19
0
def _handle_keepalive_interrupt(signum, frame):
    # type: (int, Optional[FrameType]) -> NoReturn
    raise MKTerminate()