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  }