github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/azure/value.go (about) 1 package azure 2 3 import ( 4 "strings" 5 "time" 6 7 "github.com/khulnasoft-lab/defsec/pkg/scanners/azure/arm/parser/armjson" 8 "github.com/khulnasoft-lab/defsec/pkg/types" 9 "k8s.io/utils/strings/slices" 10 ) 11 12 type EvalContext struct{} 13 14 type Kind string 15 16 const ( 17 KindUnresolvable Kind = "unresolvable" 18 KindNull Kind = "null" 19 KindBoolean Kind = "boolean" 20 KindString Kind = "string" 21 KindNumber Kind = "number" 22 KindObject Kind = "object" 23 KindArray Kind = "array" 24 KindExpression Kind = "expression" 25 ) 26 27 type Value struct { 28 types.Metadata 29 rLit interface{} 30 rMap map[string]Value 31 rArr []Value 32 Kind Kind 33 Comments []string 34 } 35 36 var NullValue = Value{ 37 Kind: KindNull, 38 } 39 40 func NewValue(value interface{}, metadata types.Metadata) Value { 41 42 v := Value{ 43 Metadata: metadata, 44 } 45 46 switch ty := value.(type) { 47 case []interface{}: 48 v.Kind = KindArray 49 for _, child := range ty { 50 if internal, ok := child.(Value); ok { 51 v.rArr = append(v.rArr, internal) 52 } else { 53 v.rArr = append(v.rArr, NewValue(child, metadata)) 54 } 55 } 56 case []Value: 57 v.Kind = KindArray 58 v.rArr = append(v.rArr, ty...) 59 60 case map[string]interface{}: 61 v.Kind = KindObject 62 v.rMap = make(map[string]Value) 63 for key, val := range ty { 64 if internal, ok := val.(Value); ok { 65 v.rMap[key] = internal 66 } else { 67 v.rMap[key] = NewValue(val, metadata) 68 } 69 } 70 case map[string]Value: 71 v.Kind = KindObject 72 v.rMap = make(map[string]Value) 73 for key, val := range ty { 74 v.rMap[key] = val 75 } 76 case string: 77 v.Kind = KindString 78 v.rLit = ty 79 case int, int64, int32, float32, float64, int8, int16, uint8, uint16, uint32, uint64: 80 v.Kind = KindNumber 81 v.rLit = ty 82 case bool: 83 v.Kind = KindBoolean 84 v.rLit = ty 85 case nil: 86 v.Kind = KindNull 87 v.rLit = ty 88 default: 89 v.Kind = KindUnresolvable 90 v.rLit = ty 91 } 92 93 return v 94 } 95 96 func (v *Value) GetMetadata() types.Metadata { 97 return v.Metadata 98 } 99 100 func (v *Value) UnmarshalJSONWithMetadata(node armjson.Node) error { 101 102 v.updateValueKind(node) 103 104 v.Metadata = node.Metadata() 105 106 switch node.Kind() { 107 case armjson.KindArray: 108 err := v.unmarshallArray(node) 109 if err != nil { 110 return err 111 } 112 case armjson.KindObject: 113 err := v.unmarshalObject(node) 114 if err != nil { 115 return err 116 } 117 case armjson.KindString: 118 err := v.unmarshalString(node) 119 if err != nil { 120 return err 121 } 122 default: 123 if err := node.Decode(&v.rLit); err != nil { 124 return err 125 } 126 } 127 128 for _, comment := range node.Comments() { 129 var str string 130 if err := comment.Decode(&str); err != nil { 131 return err 132 } 133 // remove `\r` from comment when running windows 134 str = strings.ReplaceAll(str, "\r", "") 135 136 v.Comments = append(v.Comments, str) 137 } 138 return nil 139 } 140 141 func (v *Value) unmarshalString(node armjson.Node) error { 142 var str string 143 if err := node.Decode(&str); err != nil { 144 return err 145 } 146 if strings.HasPrefix(str, "[") && !strings.HasPrefix(str, "[[") && strings.HasSuffix(str, "]") { 147 // function! 148 v.Kind = KindExpression 149 v.rLit = str[1 : len(str)-1] 150 } else { 151 v.rLit = str 152 } 153 return nil 154 } 155 156 func (v *Value) unmarshalObject(node armjson.Node) error { 157 obj := make(map[string]Value) 158 for i := 0; i < len(node.Content()); i += 2 { 159 var key string 160 if err := node.Content()[i].Decode(&key); err != nil { 161 return err 162 } 163 var val Value 164 if err := val.UnmarshalJSONWithMetadata(node.Content()[i+1]); err != nil { 165 return err 166 } 167 obj[key] = val 168 } 169 v.rMap = obj 170 return nil 171 } 172 173 func (v *Value) unmarshallArray(node armjson.Node) error { 174 var arr []Value 175 for _, child := range node.Content() { 176 var val Value 177 if err := val.UnmarshalJSONWithMetadata(child); err != nil { 178 return err 179 } 180 arr = append(arr, val) 181 } 182 v.rArr = arr 183 return nil 184 } 185 186 func (v *Value) updateValueKind(node armjson.Node) { 187 switch node.Kind() { 188 case armjson.KindString: 189 v.Kind = KindString 190 case armjson.KindNumber: 191 v.Kind = KindNumber 192 case armjson.KindBoolean: 193 v.Kind = KindBoolean 194 case armjson.KindObject: 195 v.Kind = KindObject 196 case armjson.KindNull: 197 v.Kind = KindNull 198 case armjson.KindArray: 199 v.Kind = KindArray 200 default: 201 panic(node.Kind()) 202 } 203 } 204 205 func (v Value) AsString() string { 206 v.Resolve() 207 208 if v.Kind != KindString { 209 return "" 210 } 211 212 return v.rLit.(string) 213 } 214 215 func (v Value) AsBool() bool { 216 v.Resolve() 217 if v.Kind != KindBoolean { 218 return false 219 } 220 return v.rLit.(bool) 221 } 222 223 func (v Value) AsInt() int { 224 v.Resolve() 225 if v.Kind != KindNumber { 226 return 0 227 } 228 return int(v.rLit.(int64)) 229 } 230 231 func (v Value) AsFloat() float64 { 232 v.Resolve() 233 if v.Kind != KindNumber { 234 return 0 235 } 236 return v.rLit.(float64) 237 } 238 239 func (v Value) AsIntValue(defaultValue int, metadata types.Metadata) types.IntValue { 240 v.Resolve() 241 if v.Kind != KindNumber { 242 return types.Int(defaultValue, metadata) 243 } 244 return types.Int(v.AsInt(), metadata) 245 } 246 247 func (v Value) AsBoolValue(defaultValue bool, metadata types.Metadata) types.BoolValue { 248 v.Resolve() 249 if v.Kind == KindString { 250 possibleValue := strings.ToLower(v.rLit.(string)) 251 if slices.Contains([]string{"true", "1", "yes", "on", "enabled"}, possibleValue) { 252 return types.Bool(true, metadata) 253 } 254 } 255 256 if v.Kind != KindBoolean { 257 return types.Bool(defaultValue, metadata) 258 } 259 260 return types.Bool(v.rLit.(bool), v.GetMetadata()) 261 } 262 263 func (v Value) EqualTo(value interface{}) bool { 264 switch ty := value.(type) { 265 case string: 266 return v.AsString() == ty 267 default: 268 panic("not supported") 269 } 270 } 271 272 func (v Value) AsStringValue(defaultValue string, metadata types.Metadata) types.StringValue { 273 v.Resolve() 274 if v.Kind != KindString { 275 return types.StringDefault(defaultValue, metadata) 276 } 277 return types.String(v.rLit.(string), v.Metadata) 278 } 279 280 func (v Value) GetMapValue(key string) Value { 281 v.Resolve() 282 if v.Kind != KindObject { 283 return NullValue 284 } 285 return v.rMap[key] 286 } 287 288 func (v Value) AsMap() map[string]Value { 289 v.Resolve() 290 if v.Kind != KindObject { 291 return nil 292 } 293 return v.rMap 294 } 295 296 func (v Value) AsList() []Value { 297 v.Resolve() 298 if v.Kind != KindArray { 299 return nil 300 } 301 return v.rArr 302 } 303 304 func (v Value) Raw() interface{} { 305 switch v.Kind { 306 case KindArray: 307 // TODO: recursively build raw array 308 return nil 309 case KindObject: 310 // TODO: recursively build raw object 311 return nil 312 default: 313 return v.rLit 314 } 315 } 316 317 func (v *Value) Resolve() { 318 if v.Kind != KindExpression { 319 return 320 } 321 // if resolver, ok := v.Metadata.Internal().(Resolver); ok { 322 // *v = resolver.ResolveExpression(*v) 323 // } 324 } 325 326 func (v Value) HasKey(key string) bool { 327 v.Resolve() 328 _, ok := v.rMap[key] 329 return ok 330 } 331 332 func (v Value) AsTimeValue(metadata types.Metadata) types.TimeValue { 333 v.Resolve() 334 if v.Kind != KindString { 335 return types.Time(time.Time{}, metadata) 336 } 337 if v.Kind == KindNumber { 338 return types.Time(time.Unix(int64(v.AsFloat()), 0), metadata) 339 } 340 t, err := time.Parse(time.RFC3339, v.rLit.(string)) 341 if err != nil { 342 return types.Time(time.Time{}, metadata) 343 } 344 return types.Time(t, metadata) 345 } 346 347 func (v Value) AsStringValuesList(defaultValue string) (stringValues []types.StringValue) { 348 v.Resolve() 349 if v.Kind != KindArray { 350 return 351 } 352 for _, item := range v.rArr { 353 stringValues = append(stringValues, item.AsStringValue(defaultValue, item.Metadata)) 354 } 355 356 return stringValues 357 }