1 # Copyright (c) 2016-2020 Cloudify Platform Ltd. All rights reserved
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 from copy import deepcopy
17 from ._compat import text_type
19 OBFUSCATION_KEYWORDS = ('PASSWORD', 'SECRET', 'TOKEN',)
20 OBFUSCATION_RE = re.compile(r'((password|secret|token)(:|=)\s*)(\S+)',
21 flags=re.IGNORECASE | re.MULTILINE)
22 OBFUSCATED_SECRET = 'x' * 16
25 def obfuscate_passwords(obj):
26 """Obfuscate passwords in dictionary or list of dictionaries.
28 Returns a copy of original object with elements potentially containing
29 passwords obfuscated. A copy.deepcopy() is used for copying dictionaries
30 but only when absolutely necessary. If a given object does not contain
31 any passwords, original is returned and deepcopy never performed.
33 if isinstance(obj, (text_type, bytes,)):
34 return OBFUSCATION_RE.sub('\\1{0}'.format(OBFUSCATED_SECRET), obj)
35 if isinstance(obj, list):
36 return [obfuscate_passwords(elem) for elem in obj]
37 if not isinstance(obj, dict):
40 for k, v in list(result.items()):
41 if any(x for x in OBFUSCATION_KEYWORDS if x in k.upper()):
42 a_copy = deepcopy(result)
43 a_copy[k] = OBFUSCATED_SECRET
45 if isinstance(v, (dict, list,)):
46 obfuscated_v = obfuscate_passwords(v)
47 if obfuscated_v is not v:
48 a_copy = deepcopy(result)
49 a_copy[k] = obfuscated_v