github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/kubernetes/parser/manifest_node.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "gopkg.in/yaml.v3" 8 ) 9 10 type TagType string 11 12 const ( 13 TagBool TagType = "!!bool" 14 TagInt TagType = "!!int" 15 TagFloat TagType = "!!float" 16 TagStr TagType = "!!str" 17 TagString TagType = "!!string" 18 TagSlice TagType = "!!seq" 19 TagMap TagType = "!!map" 20 ) 21 22 type ManifestNode struct { 23 StartLine int 24 EndLine int 25 Offset int 26 Value interface{} 27 Type TagType 28 Path string 29 } 30 31 func (r *ManifestNode) ToRego() interface{} { 32 if r == nil { 33 return nil 34 } 35 switch r.Type { 36 case TagBool, TagInt, TagString, TagStr: 37 return r.Value 38 case TagSlice: 39 var output []interface{} 40 for _, node := range r.Value.([]ManifestNode) { 41 output = append(output, node.ToRego()) 42 } 43 return output 44 case TagMap: 45 output := make(map[string]interface{}) 46 output["__defsec_metadata"] = map[string]interface{}{ 47 "startline": r.StartLine, 48 "endline": r.EndLine, 49 "filepath": r.Path, 50 "offset": r.Offset, 51 } 52 for key, node := range r.Value.(map[string]ManifestNode) { 53 output[key] = node.ToRego() 54 } 55 return output 56 } 57 return nil 58 } 59 60 func (r *ManifestNode) UnmarshalYAML(node *yaml.Node) error { 61 62 r.StartLine = node.Line 63 r.EndLine = node.Line 64 r.Type = TagType(node.Tag) 65 66 switch TagType(node.Tag) { 67 case TagString, TagStr: 68 69 r.Value = node.Value 70 case TagInt: 71 val, err := strconv.Atoi(node.Value) 72 if err != nil { 73 return err 74 } 75 r.Value = val 76 case TagFloat: 77 val, err := strconv.ParseFloat(node.Value, 64) 78 if err != nil { 79 return err 80 } 81 r.Value = val 82 case TagBool: 83 val, err := strconv.ParseBool(node.Value) 84 if err != nil { 85 return err 86 } 87 r.Value = val 88 case TagMap: 89 return r.handleMapTag(node) 90 case TagSlice: 91 return r.handleSliceTag(node) 92 93 default: 94 return fmt.Errorf("node tag is not supported %s", node.Tag) 95 } 96 return nil 97 } 98 99 func (r *ManifestNode) handleSliceTag(node *yaml.Node) error { 100 var nodes []ManifestNode 101 max := node.Line 102 for _, contentNode := range node.Content { 103 newNode := new(ManifestNode) 104 newNode.Path = r.Path 105 if err := contentNode.Decode(newNode); err != nil { 106 return err 107 } 108 if newNode.EndLine > max { 109 max = newNode.EndLine 110 } 111 nodes = append(nodes, *newNode) 112 } 113 r.EndLine = max 114 r.Value = nodes 115 return nil 116 } 117 118 func (r *ManifestNode) handleMapTag(node *yaml.Node) error { 119 output := make(map[string]ManifestNode) 120 var key string 121 max := node.Line 122 for i, contentNode := range node.Content { 123 if i == 0 || i%2 == 0 { 124 key = contentNode.Value 125 } else { 126 newNode := new(ManifestNode) 127 newNode.Path = r.Path 128 if err := contentNode.Decode(newNode); err != nil { 129 return err 130 } 131 output[key] = *newNode 132 if newNode.EndLine > max { 133 max = newNode.EndLine 134 } 135 } 136 } 137 r.EndLine = max 138 r.Value = output 139 return nil 140 }