github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/rules/kubernetes/policies/aquacommercial/configmap_with_sensitive.rego (about)

     1  # METADATA
     2  # title: "ConfigMap with sensitive content"
     3  # description: "Storing sensitive content such as usernames and email addresses in configMaps is unsafe"
     4  # scope: package
     5  # schemas:
     6  # - input: schema["kubernetes"]
     7  # custom:
     8  #   id: AVD-KSV-01010
     9  #   avd_id: AVD-KSV-01010
    10  #   severity: HIGH
    11  #   short_code: configMap_with_sensitive
    12  #   recommended_action: "Remove sensitive content from configMap data value"
    13  #   input:
    14  #     selector:
    15  #     - type: kubernetes
    16  
    17  package builtin.kubernetes.KSV01010
    18  
    19  import data.lib.kubernetes
    20  
    21  # More patterns can be added here, adding more patterns may lead to performance issue
    22  # some patterns are taken from https://github.com/americanexpress/earlybird/blob/d0b63538c1acbb5ab0cacf0541df5ea088d45d70/config/content.json
    23  patterns := [
    24  	"(?i)(username\\s*(=|:))",
    25  	"(?i)(email\\s*(=|:))",
    26  	"([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)",
    27  	"(?i)(key\\s*(=|:))",
    28  	"(?i)(phone\\s*(=|:))",
    29  	"[^\\.](?:\\b[A-Z]{2}\\d{2} ?\\d{4} ?\\d{4} ?\\d{4} ?\\d{4} ?[\\d]{0,2}\\b)",
    30  	"(?i)(SHA1)",
    31  	"(?i)(MD5)",
    32  ]
    33  
    34  patternsForKey := [
    35  	"(?i)(username\\s*)",
    36  	"(?i)(email\\s*)",
    37  	"([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)",
    38  	"(?i)(key\\s*)",
    39  	"(?i)(phone\\s*)",
    40  	"[^\\.](?:\\b[A-Z]{2}\\d{2} ?\\d{4} ?\\d{4} ?\\d{4} ?\\d{4} ?[\\d]{0,2}\\b)",
    41  	"(?i)(SHA1\\s*)",
    42  	"(?i)(MD5\\s*)",
    43  ]
    44  
    45  patternsForEmail := "([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)"
    46  
    47  # ConfigMapWithSensitive gives secret key
    48  # To reduce performance overhead, only matched patterns will be applied to each value for key
    49  ConfigMapWithSensitive[sensitiveData] {
    50  	kubernetes.kind == "ConfigMap"
    51  	regex.match(patterns[p], kubernetes.object.data[d])
    52  
    53  	values := split(kubernetes.object.data[d], "\n")
    54  	regex.match(patterns[p], values[v])
    55  	sensitiveData = configMapValue(values[v])
    56  }
    57  
    58  # configMapValue gives sensitive key, splitting either by '=' or ':'
    59  configMapValue(value) = sensitiveValue {
    60  	sensitiveData := split(value, ":")
    61  	count(sensitiveData) > 1
    62  	sensitiveValue = sensitiveData[0]
    63  } else = sensitiveValue {
    64  	sensitiveData := split(value, "=")
    65  	count(sensitiveData) > 1
    66  	sensitiveValue = sensitiveData[0]
    67  }
    68  
    69  #check if key has sensitive data
    70  ConfigMapWithSensitive[sensitiveData] {
    71  	kubernetes.kind == "ConfigMap"
    72  	values = split(kubernetes.object.data[d], "\n")
    73  	regex.match(patternsForKey[p], d)
    74  	sensitiveData = d
    75  }
    76  
    77  ConfigMapWithSensitive[sensitiveData] {
    78  	kubernetes.kind == "ConfigMap"
    79  	values = split(kubernetes.object.data[d], "\n")
    80  	val = split(values[v], ":")
    81  	regex.match(patternsForEmail, val[v])
    82  	sensitiveData = d
    83  }
    84  
    85  configMapSensitiveList := ConfigMapWithSensitive
    86  
    87  deny[res] {
    88  	count(configMapSensitiveList) > 0
    89  	msg := kubernetes.format(sprintf("%s '%s' in '%s' namespace stores sensitive contents in key(s) or value(s) '%s'", [kubernetes.kind, kubernetes.name, kubernetes.namespace, configMapSensitiveList]))
    90  	res := result.new(msg, kubernetes.kind)
    91  }