github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/cloudformation/parser/property_conversion.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "os" 6 "strconv" 7 "strings" 8 9 "github.com/aquasecurity/trivy-iac/pkg/scanners/cloudformation/cftypes" 10 ) 11 12 func (p *Property) IsConvertableTo(conversionType cftypes.CfType) bool { 13 switch conversionType { 14 case cftypes.Int: 15 return p.isConvertableToInt() 16 case cftypes.Bool: 17 return p.isConvertableToBool() 18 case cftypes.String: 19 return p.isConvertableToString() 20 } 21 return false 22 } 23 24 func (p *Property) isConvertableToString() bool { 25 switch p.Type() { 26 case cftypes.Map: 27 return false 28 case cftypes.List: 29 for _, p := range p.AsList() { 30 if !p.IsString() { 31 return false 32 } 33 } 34 } 35 return true 36 } 37 38 func (p *Property) isConvertableToBool() bool { 39 switch p.Type() { 40 case cftypes.String: 41 return p.EqualTo("true", IgnoreCase) || p.EqualTo("false", IgnoreCase) || 42 p.EqualTo("1", IgnoreCase) || p.EqualTo("0", IgnoreCase) 43 44 case cftypes.Int: 45 return p.EqualTo(1) || p.EqualTo(0) 46 } 47 return false 48 } 49 50 func (p *Property) isConvertableToInt() bool { 51 switch p.Type() { 52 case cftypes.String: 53 if _, err := strconv.Atoi(p.AsString()); err == nil { 54 return true 55 } 56 case cftypes.Bool: 57 return true 58 } 59 return false 60 } 61 62 func (p *Property) ConvertTo(conversionType cftypes.CfType) *Property { 63 64 if !p.IsConvertableTo(conversionType) { 65 _, _ = fmt.Fprintf(os.Stderr, "property of type %s cannot be converted to %s\n", p.Type(), conversionType) 66 return p 67 } 68 switch conversionType { 69 case cftypes.Int: 70 return p.convertToInt() 71 case cftypes.Bool: 72 return p.convertToBool() 73 case cftypes.String: 74 return p.convertToString() 75 } 76 return p 77 } 78 79 func (p *Property) convertToString() *Property { 80 switch p.Type() { 81 case cftypes.Int: 82 return p.deriveResolved(cftypes.String, strconv.Itoa(p.AsInt())) 83 case cftypes.Bool: 84 return p.deriveResolved(cftypes.String, fmt.Sprintf("%v", p.AsBool())) 85 case cftypes.List: 86 var parts []string 87 for _, property := range p.AsList() { 88 parts = append(parts, property.AsString()) 89 } 90 return p.deriveResolved(cftypes.String, fmt.Sprintf("[%s]", strings.Join(parts, ", "))) 91 } 92 return p 93 } 94 95 func (p *Property) convertToBool() *Property { 96 switch p.Type() { 97 case cftypes.String: 98 if p.EqualTo("true", IgnoreCase) || p.EqualTo("1") { 99 return p.deriveResolved(cftypes.Bool, true) 100 } 101 if p.EqualTo("false", IgnoreCase) || p.EqualTo("0") { 102 return p.deriveResolved(cftypes.Bool, false) 103 } 104 case cftypes.Int: 105 if p.EqualTo(1) { 106 return p.deriveResolved(cftypes.Bool, true) 107 } 108 if p.EqualTo(0) { 109 return p.deriveResolved(cftypes.Bool, false) 110 } 111 } 112 return p 113 } 114 115 func (p *Property) convertToInt() *Property { 116 // 117 switch p.Type() { 118 case cftypes.String: 119 if val, err := strconv.Atoi(p.AsString()); err == nil { 120 return p.deriveResolved(cftypes.Int, val) 121 } 122 case cftypes.Bool: 123 if p.IsTrue() { 124 return p.deriveResolved(cftypes.Int, 1) 125 } 126 return p.deriveResolved(cftypes.Int, 0) 127 } 128 return p 129 }