github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/cloudformation/parser/property_helpers.go (about) 1 package parser 2 3 import ( 4 "strconv" 5 "strings" 6 7 defsecTypes "github.com/aquasecurity/defsec/pkg/types" 8 9 "github.com/aquasecurity/trivy-iac/pkg/scanners/cloudformation/cftypes" 10 ) 11 12 func (p *Property) IsNil() bool { 13 return p == nil || p.Inner.Value == nil 14 } 15 16 func (p *Property) IsNotNil() bool { 17 return !p.IsUnresolved() && !p.IsNil() 18 } 19 20 func (p *Property) Is(t cftypes.CfType) bool { 21 if p.IsNil() || p.IsUnresolved() { 22 return false 23 } 24 if p.isFunction() { 25 if prop, success := p.resolveValue(); success && prop != p { 26 return prop.Is(t) 27 } 28 } 29 return p.Inner.Type == t 30 } 31 32 func (p *Property) IsString() bool { 33 return p.Is(cftypes.String) 34 } 35 36 func (p *Property) IsNotString() bool { 37 return !p.IsUnresolved() && !p.IsString() 38 } 39 40 func (p *Property) IsInt() bool { 41 return p.Is(cftypes.Int) 42 } 43 44 func (p *Property) IsNotInt() bool { 45 return !p.IsUnresolved() && !p.IsInt() 46 } 47 48 func (p *Property) IsMap() bool { 49 if p.IsNil() || p.IsUnresolved() { 50 return false 51 } 52 return p.Inner.Type == cftypes.Map 53 } 54 55 func (p *Property) IsNotMap() bool { 56 return !p.IsUnresolved() && !p.IsMap() 57 } 58 59 func (p *Property) IsList() bool { 60 return p.Is(cftypes.List) 61 } 62 63 func (p *Property) IsNotList() bool { 64 return !p.IsUnresolved() && !p.IsList() 65 } 66 67 func (p *Property) IsBool() bool { 68 return p.Is(cftypes.Bool) 69 } 70 71 func (p *Property) IsUnresolved() bool { 72 return p != nil && p.unresolved 73 } 74 75 func (p *Property) IsNotBool() bool { 76 return !p.IsUnresolved() && !p.IsBool() 77 } 78 79 func (p *Property) AsString() string { 80 if p.isFunction() { 81 if prop, success := p.resolveValue(); success && prop != p { 82 return prop.AsString() 83 } 84 return "" 85 } 86 if p.IsNil() { 87 return "" 88 } 89 if !p.IsString() { 90 return "" 91 } 92 93 return p.Inner.Value.(string) 94 } 95 96 func (p *Property) AsStringValue() defsecTypes.StringValue { 97 if p.unresolved { 98 return defsecTypes.StringUnresolvable(p.Metadata()) 99 } 100 return defsecTypes.StringExplicit(p.AsString(), p.Metadata()) 101 } 102 103 func (p *Property) AsInt() int { 104 if p.isFunction() { 105 if prop, success := p.resolveValue(); success && prop != p { 106 return prop.AsInt() 107 } 108 return 0 109 } 110 if p.IsNotInt() { 111 if p.isConvertableToInt() { 112 return p.convertToInt().AsInt() 113 } 114 return 0 115 } 116 117 return p.Inner.Value.(int) 118 } 119 120 func (p *Property) AsIntValue() defsecTypes.IntValue { 121 if p.unresolved { 122 return defsecTypes.IntUnresolvable(p.Metadata()) 123 } 124 return defsecTypes.IntExplicit(p.AsInt(), p.Metadata()) 125 } 126 127 func (p *Property) AsBool() bool { 128 if p.isFunction() { 129 if prop, success := p.resolveValue(); success && prop != p { 130 return prop.AsBool() 131 } 132 return false 133 } 134 if !p.IsBool() { 135 return false 136 } 137 return p.Inner.Value.(bool) 138 } 139 140 func (p *Property) AsBoolValue() defsecTypes.BoolValue { 141 if p.unresolved { 142 return defsecTypes.BoolUnresolvable(p.Metadata()) 143 } 144 return defsecTypes.Bool(p.AsBool(), p.Metadata()) 145 } 146 147 func (p *Property) AsMap() map[string]*Property { 148 val, ok := p.Inner.Value.(map[string]*Property) 149 if !ok { 150 return nil 151 } 152 return val 153 } 154 155 func (p *Property) AsList() []*Property { 156 if p.isFunction() { 157 if prop, success := p.resolveValue(); success && prop != p { 158 return prop.AsList() 159 } 160 return []*Property{} 161 } 162 163 if list, ok := p.Inner.Value.([]*Property); ok { 164 return list 165 } 166 return nil 167 } 168 169 func (p *Property) Len() int { 170 return len(p.AsList()) 171 } 172 173 func (p *Property) EqualTo(checkValue interface{}, equalityOptions ...EqualityOptions) bool { 174 var ignoreCase bool 175 for _, option := range equalityOptions { 176 if option == IgnoreCase { 177 ignoreCase = true 178 } 179 } 180 181 switch checkerVal := checkValue.(type) { 182 case string: 183 if p.IsNil() { 184 return false 185 } 186 187 if p.Inner.Type == cftypes.String || p.IsString() { 188 if ignoreCase { 189 return strings.EqualFold(p.AsString(), checkerVal) 190 } 191 return p.AsString() == checkerVal 192 } else if p.Inner.Type == cftypes.Int || p.IsInt() { 193 if val, err := strconv.Atoi(checkerVal); err == nil { 194 return p.AsInt() == val 195 } 196 } 197 return false 198 case bool: 199 if p.Inner.Type == cftypes.Bool || p.IsBool() { 200 return p.AsBool() == checkerVal 201 } 202 case int: 203 if p.Inner.Type == cftypes.Int || p.IsInt() { 204 return p.AsInt() == checkerVal 205 } 206 } 207 208 return false 209 210 } 211 212 func (p *Property) IsTrue() bool { 213 if p.IsNil() || !p.IsBool() { 214 return false 215 } 216 217 return p.AsBool() 218 } 219 220 func (p *Property) IsEmpty() bool { 221 222 if p.IsNil() { 223 return true 224 } 225 if p.IsUnresolved() { 226 return false 227 } 228 229 switch p.Inner.Type { 230 case cftypes.String: 231 return p.AsString() == "" 232 case cftypes.List, cftypes.Map: 233 return len(p.AsList()) == 0 234 default: 235 return false 236 } 237 } 238 239 func (p *Property) Contains(checkVal interface{}) bool { 240 if p == nil || p.IsNil() { 241 return false 242 } 243 244 switch p.Type() { 245 case cftypes.List: 246 for _, p := range p.AsList() { 247 if p.EqualTo(checkVal) { 248 return true 249 } 250 } 251 case cftypes.Map: 252 if _, ok := checkVal.(string); !ok { 253 return false 254 } 255 for key := range p.AsMap() { 256 if key == checkVal.(string) { 257 return true 258 } 259 } 260 case cftypes.String: 261 if _, ok := checkVal.(string); !ok { 262 return false 263 } 264 return strings.Contains(p.AsString(), checkVal.(string)) 265 } 266 return false 267 }