github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/cloudformation/parser/resource.go (about) 1 package parser 2 3 import ( 4 "io/fs" 5 "strings" 6 7 defsecTypes "github.com/aquasecurity/defsec/pkg/types" 8 9 "github.com/liamg/jfather" 10 "gopkg.in/yaml.v3" 11 ) 12 13 type Resource struct { 14 ctx *FileContext 15 rng defsecTypes.Range 16 id string 17 comment string 18 Inner ResourceInner 19 } 20 21 type ResourceInner struct { 22 Type string `json:"Type" yaml:"Type"` 23 Properties map[string]*Property `json:"Properties" yaml:"Properties"` 24 } 25 26 func (r *Resource) ConfigureResource(id string, target fs.FS, filepath string, ctx *FileContext) { 27 r.setId(id) 28 r.setFile(target, filepath) 29 r.setContext(ctx) 30 } 31 32 func (r *Resource) setId(id string) { 33 r.id = id 34 35 for n, p := range r.properties() { 36 p.setName(n) 37 } 38 } 39 40 func (r *Resource) setFile(target fs.FS, filepath string) { 41 r.rng = defsecTypes.NewRange(filepath, r.rng.GetStartLine(), r.rng.GetEndLine(), r.rng.GetSourcePrefix(), target) 42 43 for _, p := range r.Inner.Properties { 44 p.setFileAndParentRange(target, filepath, r.rng) 45 } 46 } 47 48 func (r *Resource) setContext(ctx *FileContext) { 49 r.ctx = ctx 50 51 for _, p := range r.Inner.Properties { 52 p.SetLogicalResource(r.id) 53 p.setContext(ctx) 54 } 55 } 56 57 func (r *Resource) UnmarshalYAML(value *yaml.Node) error { 58 r.rng = defsecTypes.NewRange("", value.Line-1, calculateEndLine(value), "", nil) 59 r.comment = value.LineComment 60 return value.Decode(&r.Inner) 61 } 62 63 func (r *Resource) UnmarshalJSONWithMetadata(node jfather.Node) error { 64 r.rng = defsecTypes.NewRange("", node.Range().Start.Line, node.Range().End.Line, "", nil) 65 return node.Decode(&r.Inner) 66 } 67 68 func (r *Resource) ID() string { 69 return r.id 70 } 71 72 func (r *Resource) Type() string { 73 return r.Inner.Type 74 } 75 76 func (r *Resource) Range() defsecTypes.Range { 77 return r.rng 78 } 79 80 func (r *Resource) SourceFormat() SourceFormat { 81 return r.ctx.SourceFormat 82 } 83 84 func (r *Resource) Metadata() defsecTypes.Metadata { 85 return defsecTypes.NewMetadata(r.Range(), NewCFReference(r.id, r.rng).String()) 86 } 87 88 func (r *Resource) properties() map[string]*Property { 89 return r.Inner.Properties 90 } 91 92 func (r *Resource) IsNil() bool { 93 return r.id == "" 94 } 95 96 func (r *Resource) GetProperty(path string) *Property { 97 98 pathParts := strings.Split(path, ".") 99 100 first := pathParts[0] 101 property := &Property{} 102 103 for n, p := range r.properties() { 104 if n == first { 105 property = p 106 break 107 } 108 } 109 110 if len(pathParts) == 1 || property.IsNil() { 111 if property.isFunction() { 112 resolved, _ := property.resolveValue() 113 return resolved 114 } 115 return property 116 } 117 118 if nestedProperty := property.GetProperty(strings.Join(pathParts[1:], ".")); nestedProperty != nil { 119 return nestedProperty 120 } 121 122 return &Property{} 123 } 124 125 func (r *Resource) GetStringProperty(path string, defaultValue ...string) defsecTypes.StringValue { 126 defVal := "" 127 if len(defaultValue) > 0 { 128 defVal = defaultValue[0] 129 } 130 131 prop := r.GetProperty(path) 132 133 if prop.IsNotString() { 134 return r.StringDefault(defVal) 135 } 136 return prop.AsStringValue() 137 } 138 139 func (r *Resource) GetBoolProperty(path string, defaultValue ...bool) defsecTypes.BoolValue { 140 defVal := false 141 if len(defaultValue) > 0 { 142 defVal = defaultValue[0] 143 } 144 145 prop := r.GetProperty(path) 146 147 if prop.IsNotBool() { 148 return r.inferBool(prop, defVal) 149 } 150 return prop.AsBoolValue() 151 } 152 153 func (r *Resource) GetIntProperty(path string, defaultValue ...int) defsecTypes.IntValue { 154 defVal := 0 155 if len(defaultValue) > 0 { 156 defVal = defaultValue[0] 157 } 158 159 prop := r.GetProperty(path) 160 161 if prop.IsNotInt() { 162 return r.IntDefault(defVal) 163 } 164 return prop.AsIntValue() 165 } 166 167 func (r *Resource) StringDefault(defaultValue string) defsecTypes.StringValue { 168 return defsecTypes.StringDefault(defaultValue, r.Metadata()) 169 } 170 171 func (r *Resource) BoolDefault(defaultValue bool) defsecTypes.BoolValue { 172 return defsecTypes.BoolDefault(defaultValue, r.Metadata()) 173 } 174 175 func (r *Resource) IntDefault(defaultValue int) defsecTypes.IntValue { 176 return defsecTypes.IntDefault(defaultValue, r.Metadata()) 177 } 178 179 func (r *Resource) inferBool(prop *Property, defaultValue bool) defsecTypes.BoolValue { 180 if prop.IsString() { 181 if prop.EqualTo("true", IgnoreCase) { 182 return defsecTypes.Bool(true, prop.Metadata()) 183 } 184 if prop.EqualTo("yes", IgnoreCase) { 185 return defsecTypes.Bool(true, prop.Metadata()) 186 } 187 if prop.EqualTo("1", IgnoreCase) { 188 return defsecTypes.Bool(true, prop.Metadata()) 189 } 190 if prop.EqualTo("false", IgnoreCase) { 191 return defsecTypes.Bool(false, prop.Metadata()) 192 } 193 if prop.EqualTo("no", IgnoreCase) { 194 return defsecTypes.Bool(false, prop.Metadata()) 195 } 196 if prop.EqualTo("0", IgnoreCase) { 197 return defsecTypes.Bool(false, prop.Metadata()) 198 } 199 } 200 201 if prop.IsInt() { 202 if prop.EqualTo(0) { 203 return defsecTypes.Bool(false, prop.Metadata()) 204 } 205 if prop.EqualTo(1) { 206 return defsecTypes.Bool(true, prop.Metadata()) 207 } 208 } 209 210 return r.BoolDefault(defaultValue) 211 }