github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/cloudformation/parser/parameter.go (about) 1 package parser 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "strconv" 8 "strings" 9 10 "github.com/liamg/jfather" 11 "gopkg.in/yaml.v3" 12 13 "github.com/aquasecurity/trivy-iac/pkg/scanners/cloudformation/cftypes" 14 ) 15 16 type Parameter struct { 17 inner parameterInner 18 } 19 20 type parameterInner struct { 21 Type string `yaml:"Type"` 22 Default interface{} `yaml:"Default"` 23 } 24 25 func (p *Parameter) UnmarshalYAML(node *yaml.Node) error { 26 return node.Decode(&p.inner) 27 } 28 29 func (p *Parameter) UnmarshalJSONWithMetadata(node jfather.Node) error { 30 return node.Decode(&p.inner) 31 } 32 33 func (p *Parameter) Type() cftypes.CfType { 34 switch p.inner.Type { 35 case "Boolean": 36 return cftypes.Bool 37 case "String": 38 return cftypes.String 39 case "Integer": 40 return cftypes.Int 41 default: 42 return cftypes.String 43 } 44 } 45 46 func (p *Parameter) Default() interface{} { 47 return p.inner.Default 48 } 49 50 func (p *Parameter) UpdateDefault(inVal interface{}) { 51 passedVal := inVal.(string) 52 53 switch p.inner.Type { 54 case "Boolean": 55 p.inner.Default, _ = strconv.ParseBool(passedVal) 56 case "String": 57 p.inner.Default = passedVal 58 case "Integer": 59 p.inner.Default, _ = strconv.Atoi(passedVal) 60 default: 61 p.inner.Default = passedVal 62 } 63 } 64 65 type Parameters map[string]any 66 67 func (p *Parameters) Merge(other Parameters) { 68 for k, v := range other { 69 (*p)[k] = v 70 } 71 } 72 73 func (p *Parameters) UnmarshalJSON(data []byte) error { 74 (*p) = make(Parameters) 75 76 if len(data) == 0 { 77 return nil 78 } 79 80 switch { 81 case data[0] == '{' && data[len(data)-1] == '}': // object 82 // CodePipeline like format 83 var params struct { 84 Params map[string]any `json:"Parameters"` 85 } 86 87 if err := json.Unmarshal(data, ¶ms); err != nil { 88 return err 89 } 90 91 (*p) = params.Params 92 case data[0] == '[' && data[len(data)-1] == ']': // array 93 { 94 // Original format 95 var params []string 96 97 if err := json.Unmarshal(data, ¶ms); err == nil { 98 for _, param := range params { 99 parts := strings.Split(param, "=") 100 if len(parts) != 2 { 101 return fmt.Errorf("invalid key-value parameter: %q", param) 102 } 103 (*p)[parts[0]] = parts[1] 104 } 105 return nil 106 } 107 108 // CloudFormation like format 109 var cfparams []struct { 110 ParameterKey string `json:"ParameterKey"` 111 ParameterValue string `json:"ParameterValue"` 112 } 113 114 d := json.NewDecoder(bytes.NewReader(data)) 115 d.DisallowUnknownFields() 116 if err := d.Decode(&cfparams); err != nil { 117 return err 118 } 119 120 for _, param := range cfparams { 121 (*p)[param.ParameterKey] = param.ParameterValue 122 } 123 } 124 default: 125 return fmt.Errorf("unsupported parameters format") 126 } 127 128 return nil 129 }