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  }