134 lines
4.0 KiB
Go
134 lines
4.0 KiB
Go
|
package logging
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
|
||
|
"github.com/hashicorp/terraform-plugin-log/internal/fieldutils"
|
||
|
"github.com/hashicorp/terraform-plugin-log/internal/hclogutils"
|
||
|
)
|
||
|
|
||
|
const logMaskingReplacementString = "***"
|
||
|
|
||
|
// ShouldOmit takes a log's *string message and slices of fields,
|
||
|
// and determines, based on the LoggerOpts configuration, if the
|
||
|
// log should be omitted (i.e. prevent it to be printed on the final writer).
|
||
|
func (lo LoggerOpts) ShouldOmit(msg *string, fieldMaps ...map[string]interface{}) bool {
|
||
|
// Omit log if any of the configured keys is found in the given fields
|
||
|
if len(lo.OmitLogWithFieldKeys) > 0 {
|
||
|
fieldsKeys := fieldutils.FieldMapsToKeys(fieldMaps...)
|
||
|
if argKeysContain(fieldsKeys, lo.OmitLogWithFieldKeys) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Omit log if any of the configured regexp matches the log message
|
||
|
if len(lo.OmitLogWithMessageRegexes) > 0 {
|
||
|
for _, r := range lo.OmitLogWithMessageRegexes {
|
||
|
if r.MatchString(*msg) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Omit log if any of the configured strings is contained in the log message
|
||
|
if len(lo.OmitLogWithMessageStrings) > 0 {
|
||
|
for _, s := range lo.OmitLogWithMessageStrings {
|
||
|
if strings.Contains(*msg, s) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// ApplyMask takes a log's *string message and slices of fields,
|
||
|
// and applies masking to fields keys' values and/or to log message,
|
||
|
// based on the LoggerOpts configuration.
|
||
|
//
|
||
|
// Note that the given input is changed-in-place by this method.
|
||
|
func (lo LoggerOpts) ApplyMask(msg *string, fieldMaps ...map[string]interface{}) {
|
||
|
// Replace any log field value with the corresponding field key equal to the configured strings
|
||
|
if len(lo.MaskFieldValuesWithFieldKeys) > 0 {
|
||
|
for _, k := range lo.MaskFieldValuesWithFieldKeys {
|
||
|
for _, f := range fieldMaps {
|
||
|
for fk := range f {
|
||
|
if k == fk {
|
||
|
f[k] = logMaskingReplacementString
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Replace any part of any log field matching any of the configured regexp
|
||
|
if len(lo.MaskAllFieldValuesRegexes) > 0 {
|
||
|
for _, r := range lo.MaskAllFieldValuesRegexes {
|
||
|
for _, f := range fieldMaps {
|
||
|
for fk, fv := range f {
|
||
|
// Can apply the regexp replacement, only if the field value is indeed a string
|
||
|
fvStr, ok := fv.(string)
|
||
|
if ok {
|
||
|
f[fk] = r.ReplaceAllString(fvStr, logMaskingReplacementString)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Replace any part of any log field matching any of the configured strings
|
||
|
if len(lo.MaskAllFieldValuesStrings) > 0 {
|
||
|
for _, s := range lo.MaskAllFieldValuesStrings {
|
||
|
for _, f := range fieldMaps {
|
||
|
for fk, fv := range f {
|
||
|
// Can apply the regexp replacement, only if the field value is indeed a string
|
||
|
fvStr, ok := fv.(string)
|
||
|
if ok {
|
||
|
f[fk] = strings.ReplaceAll(fvStr, s, logMaskingReplacementString)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Replace any part of the log message matching any of the configured regexp
|
||
|
if len(lo.MaskMessageRegexes) > 0 {
|
||
|
for _, r := range lo.MaskMessageRegexes {
|
||
|
*msg = r.ReplaceAllString(*msg, logMaskingReplacementString)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Replace any part of the log message equal to any of the configured strings
|
||
|
if len(lo.MaskMessageStrings) > 0 {
|
||
|
for _, s := range lo.MaskMessageStrings {
|
||
|
*msg = strings.ReplaceAll(*msg, s, logMaskingReplacementString)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func OmitOrMask(tfLoggerOpts LoggerOpts, msg *string, additionalFields []map[string]interface{}) ([]interface{}, bool) {
|
||
|
additionalFieldsMap := fieldutils.MergeFieldMaps(additionalFields...)
|
||
|
|
||
|
// Apply the provider root LoggerOpts to determine if this log should be omitted
|
||
|
if tfLoggerOpts.ShouldOmit(msg, tfLoggerOpts.Fields, additionalFieldsMap) {
|
||
|
return nil, true
|
||
|
}
|
||
|
|
||
|
// Apply the provider root LoggerOpts to apply masking to this log
|
||
|
tfLoggerOpts.ApplyMask(msg, tfLoggerOpts.Fields, additionalFieldsMap)
|
||
|
|
||
|
return hclogutils.FieldMapsToArgs(tfLoggerOpts.Fields, additionalFieldsMap), false
|
||
|
}
|
||
|
|
||
|
func argKeysContain(haystack []string, needles []string) bool {
|
||
|
for _, h := range haystack {
|
||
|
for _, n := range needles {
|
||
|
if n == h {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
}
|