1#
2# Copyright 2016 SUSE LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17import fnmatch
18import os.path
19import re
20
21import salt.utils.stringutils
22from salt.exceptions import CommandExecutionError
23
24
25class InputSanitizer:
26    @staticmethod
27    def trim(value):
28        """
29        Raise an exception if value is empty. Otherwise strip it down.
30        :param value:
31        :return:
32        """
33        value = (value or "").strip()
34        if not value:
35            raise CommandExecutionError("Empty value during sanitation")
36
37        return str(value)
38
39    @staticmethod
40    def filename(value):
41        """
42        Remove everything that would affect paths in the filename
43
44        :param value:
45        :return:
46        """
47        return re.sub(
48            "[^a-zA-Z0-9.-_ ]", "", os.path.basename(InputSanitizer.trim(value))
49        )
50
51    @staticmethod
52    def hostname(value):
53        """
54        Clean value for RFC1123.
55
56        :param value:
57        :return:
58        """
59        return re.sub(r"[^a-zA-Z0-9.-]", "", InputSanitizer.trim(value)).strip(".")
60
61    id = hostname
62
63
64clean = InputSanitizer()
65
66
67def mask_args_value(data, mask):
68    """
69    Mask a line in the data, which matches "mask".
70
71    This can be used for cases where values in your roster file may contain
72    sensitive data such as IP addresses, passwords, user names, etc.
73
74    Note that this works only when ``data`` is a single string (i.e. when the
75    data in the roster is formatted as ``key: value`` pairs in YAML syntax).
76
77    :param data: String data, already rendered.
78    :param mask: Mask that matches a single line
79
80    :return:
81    """
82    if not mask:
83        return data
84
85    out = []
86    for line in data.split(os.linesep):
87        if fnmatch.fnmatch(line.strip(), mask) and ":" in line:
88            key, value = line.split(":", 1)
89            out.append(
90                "{}: {}".format(
91                    salt.utils.stringutils.to_unicode(key.strip()), "** hidden **"
92                )
93            )
94        else:
95            out.append(line)
96
97    return "\n".join(out)
98