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

     1  package parser
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/aquasecurity/trivy-iac/pkg/scanners/cloudformation/cftypes"
     9  )
    10  
    11  func ResolveSub(property *Property) (resolved *Property, success bool) {
    12  	if !property.isFunction() {
    13  		return property, true
    14  	}
    15  
    16  	refValue := property.AsMap()["Fn::Sub"]
    17  
    18  	if refValue.IsString() {
    19  		return resolveStringSub(refValue, property), true
    20  	}
    21  
    22  	if refValue.IsList() {
    23  		return resolveMapSub(refValue, property)
    24  	}
    25  
    26  	return property, false
    27  }
    28  
    29  func resolveMapSub(refValue *Property, original *Property) (*Property, bool) {
    30  	refValues := refValue.AsList()
    31  	if len(refValues) != 2 {
    32  		return abortIntrinsic(original, "Fn::Sub with list expects 2 values, returning original property")
    33  	}
    34  
    35  	workingString := refValues[0].AsString()
    36  	components := refValues[1].AsMap()
    37  
    38  	for k, v := range components {
    39  		replacement := "[failed to resolve]"
    40  		switch v.Type() {
    41  		case cftypes.Map:
    42  			resolved, _ := ResolveIntrinsicFunc(v)
    43  			replacement = resolved.AsString()
    44  		case cftypes.String:
    45  			replacement = v.AsString()
    46  		case cftypes.Int:
    47  			replacement = strconv.Itoa(v.AsInt())
    48  		case cftypes.Bool:
    49  			replacement = fmt.Sprintf("%v", v.AsBool())
    50  		case cftypes.List:
    51  			var parts []string
    52  			for _, p := range v.AsList() {
    53  				parts = append(parts, p.String())
    54  			}
    55  			replacement = fmt.Sprintf("[%s]", strings.Join(parts, ", "))
    56  		}
    57  		workingString = strings.ReplaceAll(workingString, fmt.Sprintf("${%s}", k), replacement)
    58  	}
    59  
    60  	return original.deriveResolved(cftypes.String, workingString), true
    61  }
    62  
    63  func resolveStringSub(refValue *Property, original *Property) *Property {
    64  	workingString := refValue.AsString()
    65  
    66  	for k, param := range pseudoParameters {
    67  		workingString = strings.ReplaceAll(workingString, fmt.Sprintf("${%s}", k), fmt.Sprintf("%v", param.getRawValue()))
    68  	}
    69  
    70  	return original.deriveResolved(cftypes.String, workingString)
    71  }