go.temporal.io/server@v1.23.0/common/masker/masker.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package masker 26 27 import ( 28 "reflect" 29 30 "gopkg.in/yaml.v3" 31 ) 32 33 const passwordMask = "******" 34 35 var ( 36 DefaultFieldNames = []string{"Password", "KeyData"} 37 DefaultYAMLFieldNames = []string{"password", "keyData"} 38 ) 39 40 // MaskYaml replace password values with mask and returns copy of the string. 41 // Does recursive replacement for entire yamlStr. 42 func MaskYaml(yamlStr string, fieldNamesToMask []string) (string, error) { 43 fns := make(map[string]struct{}, len(fieldNamesToMask)) 44 for _, fieldName := range fieldNamesToMask { 45 fns[fieldName] = struct{}{} 46 } 47 48 var parsedYaml map[string]interface{} 49 err := yaml.Unmarshal([]byte(yamlStr), &parsedYaml) 50 if err != nil { 51 return yamlStr, err 52 } 53 54 maskMap(parsedYaml, fns) 55 56 strBytes, err := yaml.Marshal(parsedYaml) 57 if err != nil { 58 return yamlStr, err 59 } 60 return string(strBytes), nil 61 } 62 63 // MaskStruct replace password values with mask and returns copy of the strct. 64 // Original strct value is not modified. Doesn't go recursively through strct properties. 65 func MaskStruct(strct interface{}, fieldNamesToMask []string) interface{} { 66 strctV := reflect.ValueOf(strct) 67 68 if strct == nil || (strctV.Kind() == reflect.Ptr && strctV.IsNil()) { 69 return strct 70 } 71 72 for t := reflect.TypeOf(strct); t.Kind() == reflect.Ptr; t = t.Elem() { 73 strctV = strctV.Elem() 74 } 75 76 // strctV is not a pointer now. Create a copy using assignment. 77 strctCopy := strctV.Interface() 78 strctCopyPV := pointerTo(strctCopy) 79 strctCopyV := strctCopyPV.Elem() 80 81 for _, passwordFieldName := range fieldNamesToMask { 82 passwordF := strctCopyV.FieldByName(passwordFieldName) 83 if passwordF.CanSet() && passwordF.Kind() == reflect.String { 84 passwordF.SetString(passwordMask) 85 } 86 } 87 88 return strctCopyPV.Interface() 89 } 90 91 func pointerTo(val interface{}) reflect.Value { 92 valPtr := reflect.New(reflect.TypeOf(val)) 93 valPtr.Elem().Set(reflect.ValueOf(val)) 94 return valPtr 95 } 96 97 func maskMap(m map[string]interface{}, fns map[string]struct{}) { 98 for key, value := range m { 99 if _, ok := fns[key]; ok { 100 m[key] = passwordMask 101 } 102 103 if valueMap, ok := value.(map[string]interface{}); ok { 104 maskMap(valueMap, fns) 105 } 106 } 107 }