github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/cloudformation/parser/resource.go (about)

     1  package parser
     2  
     3  import (
     4  	"io/fs"
     5  	"strings"
     6  
     7  	defsecTypes "github.com/aquasecurity/defsec/pkg/types"
     8  
     9  	"github.com/liamg/jfather"
    10  	"gopkg.in/yaml.v3"
    11  )
    12  
    13  type Resource struct {
    14  	ctx     *FileContext
    15  	rng     defsecTypes.Range
    16  	id      string
    17  	comment string
    18  	Inner   ResourceInner
    19  }
    20  
    21  type ResourceInner struct {
    22  	Type       string               `json:"Type" yaml:"Type"`
    23  	Properties map[string]*Property `json:"Properties" yaml:"Properties"`
    24  }
    25  
    26  func (r *Resource) ConfigureResource(id string, target fs.FS, filepath string, ctx *FileContext) {
    27  	r.setId(id)
    28  	r.setFile(target, filepath)
    29  	r.setContext(ctx)
    30  }
    31  
    32  func (r *Resource) setId(id string) {
    33  	r.id = id
    34  
    35  	for n, p := range r.properties() {
    36  		p.setName(n)
    37  	}
    38  }
    39  
    40  func (r *Resource) setFile(target fs.FS, filepath string) {
    41  	r.rng = defsecTypes.NewRange(filepath, r.rng.GetStartLine(), r.rng.GetEndLine(), r.rng.GetSourcePrefix(), target)
    42  
    43  	for _, p := range r.Inner.Properties {
    44  		p.setFileAndParentRange(target, filepath, r.rng)
    45  	}
    46  }
    47  
    48  func (r *Resource) setContext(ctx *FileContext) {
    49  	r.ctx = ctx
    50  
    51  	for _, p := range r.Inner.Properties {
    52  		p.SetLogicalResource(r.id)
    53  		p.setContext(ctx)
    54  	}
    55  }
    56  
    57  func (r *Resource) UnmarshalYAML(value *yaml.Node) error {
    58  	r.rng = defsecTypes.NewRange("", value.Line-1, calculateEndLine(value), "", nil)
    59  	r.comment = value.LineComment
    60  	return value.Decode(&r.Inner)
    61  }
    62  
    63  func (r *Resource) UnmarshalJSONWithMetadata(node jfather.Node) error {
    64  	r.rng = defsecTypes.NewRange("", node.Range().Start.Line, node.Range().End.Line, "", nil)
    65  	return node.Decode(&r.Inner)
    66  }
    67  
    68  func (r *Resource) ID() string {
    69  	return r.id
    70  }
    71  
    72  func (r *Resource) Type() string {
    73  	return r.Inner.Type
    74  }
    75  
    76  func (r *Resource) Range() defsecTypes.Range {
    77  	return r.rng
    78  }
    79  
    80  func (r *Resource) SourceFormat() SourceFormat {
    81  	return r.ctx.SourceFormat
    82  }
    83  
    84  func (r *Resource) Metadata() defsecTypes.Metadata {
    85  	return defsecTypes.NewMetadata(r.Range(), NewCFReference(r.id, r.rng).String())
    86  }
    87  
    88  func (r *Resource) properties() map[string]*Property {
    89  	return r.Inner.Properties
    90  }
    91  
    92  func (r *Resource) IsNil() bool {
    93  	return r.id == ""
    94  }
    95  
    96  func (r *Resource) GetProperty(path string) *Property {
    97  
    98  	pathParts := strings.Split(path, ".")
    99  
   100  	first := pathParts[0]
   101  	property := &Property{}
   102  
   103  	for n, p := range r.properties() {
   104  		if n == first {
   105  			property = p
   106  			break
   107  		}
   108  	}
   109  
   110  	if len(pathParts) == 1 || property.IsNil() {
   111  		if property.isFunction() {
   112  			resolved, _ := property.resolveValue()
   113  			return resolved
   114  		}
   115  		return property
   116  	}
   117  
   118  	if nestedProperty := property.GetProperty(strings.Join(pathParts[1:], ".")); nestedProperty != nil {
   119  		return nestedProperty
   120  	}
   121  
   122  	return &Property{}
   123  }
   124  
   125  func (r *Resource) GetStringProperty(path string, defaultValue ...string) defsecTypes.StringValue {
   126  	defVal := ""
   127  	if len(defaultValue) > 0 {
   128  		defVal = defaultValue[0]
   129  	}
   130  
   131  	prop := r.GetProperty(path)
   132  
   133  	if prop.IsNotString() {
   134  		return r.StringDefault(defVal)
   135  	}
   136  	return prop.AsStringValue()
   137  }
   138  
   139  func (r *Resource) GetBoolProperty(path string, defaultValue ...bool) defsecTypes.BoolValue {
   140  	defVal := false
   141  	if len(defaultValue) > 0 {
   142  		defVal = defaultValue[0]
   143  	}
   144  
   145  	prop := r.GetProperty(path)
   146  
   147  	if prop.IsNotBool() {
   148  		return r.inferBool(prop, defVal)
   149  	}
   150  	return prop.AsBoolValue()
   151  }
   152  
   153  func (r *Resource) GetIntProperty(path string, defaultValue ...int) defsecTypes.IntValue {
   154  	defVal := 0
   155  	if len(defaultValue) > 0 {
   156  		defVal = defaultValue[0]
   157  	}
   158  
   159  	prop := r.GetProperty(path)
   160  
   161  	if prop.IsNotInt() {
   162  		return r.IntDefault(defVal)
   163  	}
   164  	return prop.AsIntValue()
   165  }
   166  
   167  func (r *Resource) StringDefault(defaultValue string) defsecTypes.StringValue {
   168  	return defsecTypes.StringDefault(defaultValue, r.Metadata())
   169  }
   170  
   171  func (r *Resource) BoolDefault(defaultValue bool) defsecTypes.BoolValue {
   172  	return defsecTypes.BoolDefault(defaultValue, r.Metadata())
   173  }
   174  
   175  func (r *Resource) IntDefault(defaultValue int) defsecTypes.IntValue {
   176  	return defsecTypes.IntDefault(defaultValue, r.Metadata())
   177  }
   178  
   179  func (r *Resource) inferBool(prop *Property, defaultValue bool) defsecTypes.BoolValue {
   180  	if prop.IsString() {
   181  		if prop.EqualTo("true", IgnoreCase) {
   182  			return defsecTypes.Bool(true, prop.Metadata())
   183  		}
   184  		if prop.EqualTo("yes", IgnoreCase) {
   185  			return defsecTypes.Bool(true, prop.Metadata())
   186  		}
   187  		if prop.EqualTo("1", IgnoreCase) {
   188  			return defsecTypes.Bool(true, prop.Metadata())
   189  		}
   190  		if prop.EqualTo("false", IgnoreCase) {
   191  			return defsecTypes.Bool(false, prop.Metadata())
   192  		}
   193  		if prop.EqualTo("no", IgnoreCase) {
   194  			return defsecTypes.Bool(false, prop.Metadata())
   195  		}
   196  		if prop.EqualTo("0", IgnoreCase) {
   197  			return defsecTypes.Bool(false, prop.Metadata())
   198  		}
   199  	}
   200  
   201  	if prop.IsInt() {
   202  		if prop.EqualTo(0) {
   203  			return defsecTypes.Bool(false, prop.Metadata())
   204  		}
   205  		if prop.EqualTo(1) {
   206  			return defsecTypes.Bool(true, prop.Metadata())
   207  		}
   208  	}
   209  
   210  	return r.BoolDefault(defaultValue)
   211  }