Skip to content

Commit

Permalink
refactor(terraform): sync funcs with Terraform (aquasecurity#6415)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikpivkin authored Apr 6, 2024
1 parent 53517d6 commit a51cedd
Show file tree
Hide file tree
Showing 17 changed files with 711 additions and 906 deletions.
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ run:
- ".*_test.go$"
- "integration/*"
- "examples/*"
skip-dirs:
- "pkg/iac/scanners/terraform/parser/funcs" # copies of Terraform functions

issues:
exclude-rules:
Expand Down
51 changes: 17 additions & 34 deletions pkg/iac/scanners/terraform/parser/funcs/cidr.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package funcs
import (
"fmt"
"math/big"
"net"

"github.com/apparentlymart/go-cidr/cidr"
"github.com/zclconf/go-cty/cty"
Expand All @@ -25,13 +24,14 @@ var CidrHostFunc = function.New(&function.Spec{
Type: cty.Number,
},
},
Type: function.StaticReturnType(cty.String),
Type: function.StaticReturnType(cty.String),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
var hostNum *big.Int
if err := gocty.FromCtyValue(args[1], &hostNum); err != nil {
return cty.UnknownVal(cty.String), err
}
_, network, err := net.ParseCIDR(args[0].AsString())
_, network, err := ParseCIDR(args[0].AsString())
if err != nil {
return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
}
Expand All @@ -54,14 +54,19 @@ var CidrNetmaskFunc = function.New(&function.Spec{
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.String),
Type: function.StaticReturnType(cty.String),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
_, network, err := net.ParseCIDR(args[0].AsString())
_, network, err := ParseCIDR(args[0].AsString())
if err != nil {
return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
}

return cty.StringVal(net.IP(network.Mask).String()), nil
if network.IP.To4() == nil {
return cty.UnknownVal(cty.String), fmt.Errorf("IPv6 addresses cannot have a netmask: %s", args[0].AsString())
}

return cty.StringVal(IP(network.Mask).String()), nil
},
})

Expand All @@ -82,7 +87,8 @@ var CidrSubnetFunc = function.New(&function.Spec{
Type: cty.Number,
},
},
Type: function.StaticReturnType(cty.String),
Type: function.StaticReturnType(cty.String),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
var newbits int
if err := gocty.FromCtyValue(args[1], &newbits); err != nil {
Expand All @@ -93,7 +99,7 @@ var CidrSubnetFunc = function.New(&function.Spec{
return cty.UnknownVal(cty.String), err
}

_, network, err := net.ParseCIDR(args[0].AsString())
_, network, err := ParseCIDR(args[0].AsString())
if err != nil {
return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
}
Expand All @@ -120,9 +126,10 @@ var CidrSubnetsFunc = function.New(&function.Spec{
Name: "newbits",
Type: cty.Number,
},
Type: function.StaticReturnType(cty.List(cty.String)),
Type: function.StaticReturnType(cty.List(cty.String)),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
_, network, err := net.ParseCIDR(args[0].AsString())
_, network, err := ParseCIDR(args[0].AsString())
if err != nil {
return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "invalid CIDR expression: %s", err)
}
Expand Down Expand Up @@ -186,27 +193,3 @@ var CidrSubnetsFunc = function.New(&function.Spec{
return cty.ListVal(retVals), nil
},
})

// CidrHost calculates a full host IP address within a given IP network address prefix.
func CidrHost(prefix, hostnum cty.Value) (cty.Value, error) {
return CidrHostFunc.Call([]cty.Value{prefix, hostnum})
}

// CidrNetmask converts an IPv4 address prefix given in CIDR notation into a subnet mask address.
func CidrNetmask(prefix cty.Value) (cty.Value, error) {
return CidrNetmaskFunc.Call([]cty.Value{prefix})
}

// CidrSubnet calculates a subnet address within a given IP network address prefix.
func CidrSubnet(prefix, newbits, netnum cty.Value) (cty.Value, error) {
return CidrSubnetFunc.Call([]cty.Value{prefix, newbits, netnum})
}

// CidrSubnets calculates a sequence of consecutive subnet prefixes that may
// be of different prefix lengths under a common base prefix.
func CidrSubnets(prefix cty.Value, newbits ...cty.Value) (cty.Value, error) {
args := make([]cty.Value, len(newbits)+1)
args[0] = prefix
copy(args[1:], newbits)
return CidrSubnetsFunc.Call(args)
}
105 changes: 23 additions & 82 deletions pkg/iac/scanners/terraform/parser/funcs/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var LengthFunc = function.New(&function.Spec{
return cty.Number, errors.New("argument must be a string, a collection type, or a structural type")
}
},
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
coll := args[0]
collTy := args[0].Type()
Expand Down Expand Up @@ -69,7 +70,8 @@ var AllTrueFunc = function.New(&function.Spec{
Type: cty.List(cty.Bool),
},
},
Type: function.StaticReturnType(cty.Bool),
Type: function.StaticReturnType(cty.Bool),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
result := cty.True
for it := args[0].ElementIterator(); it.Next(); {
Expand Down Expand Up @@ -98,7 +100,8 @@ var AnyTrueFunc = function.New(&function.Spec{
Type: cty.List(cty.Bool),
},
},
Type: function.StaticReturnType(cty.Bool),
Type: function.StaticReturnType(cty.Bool),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
result := cty.False
var hasUnknown bool
Expand Down Expand Up @@ -147,6 +150,7 @@ var CoalesceFunc = function.New(&function.Spec{
}
return retType, nil
},
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
for _, argVal := range args {
// We already know this will succeed because of the checks in our Type func above
Expand Down Expand Up @@ -179,7 +183,8 @@ var IndexFunc = function.New(&function.Spec{
Type: cty.DynamicPseudoType,
},
},
Type: function.StaticReturnType(cty.Number),
Type: function.StaticReturnType(cty.Number),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !(args[0].Type().IsListType() || args[0].Type().IsTupleType()) {
return cty.NilVal, errors.New("argument must be a list or tuple")
Expand Down Expand Up @@ -312,8 +317,8 @@ var LookupFunc = function.New(&function.Spec{
return defaultVal.WithMarks(markses...), nil
}

return cty.UnknownVal(cty.DynamicPseudoType).WithMarks(markses...), fmt.Errorf(
"lookup failed to find '%s'", lookupKey)
return cty.UnknownVal(cty.DynamicPseudoType), fmt.Errorf(
"lookup failed to find key %s", redactIfSensitive(lookupKey, keyMarks))
},
})

Expand Down Expand Up @@ -344,6 +349,7 @@ var MatchkeysFunc = function.New(&function.Spec{
// the return type is based on args[0] (values)
return args[0].Type(), nil
},
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !args[0].IsKnown() {
return cty.UnknownVal(cty.List(retType.ElementType())), nil
Expand All @@ -353,7 +359,7 @@ var MatchkeysFunc = function.New(&function.Spec{
return cty.ListValEmpty(retType.ElementType()), errors.New("length of keys and values should be equal")
}

var output []cty.Value
output := make([]cty.Value, 0)
values := args[0]

// Keys and searchset must be the same type.
Expand Down Expand Up @@ -487,7 +493,8 @@ var SumFunc = function.New(&function.Spec{
Type: cty.DynamicPseudoType,
},
},
Type: function.StaticReturnType(cty.Number),
Type: function.StaticReturnType(cty.Number),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {

if !args[0].CanIterateElements() {
Expand Down Expand Up @@ -528,6 +535,10 @@ var SumFunc = function.New(&function.Spec{
if s.IsNull() {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
}
s, err = convert.Convert(s, cty.Number)
if err != nil {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
}
for _, v := range arg[1:] {
if v.IsNull() {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
Expand All @@ -552,7 +563,8 @@ var TransposeFunc = function.New(&function.Spec{
Type: cty.Map(cty.List(cty.String)),
},
},
Type: function.StaticReturnType(cty.Map(cty.List(cty.String))),
Type: function.StaticReturnType(cty.Map(cty.List(cty.String))),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
inputMap := args[0]
if !inputMap.IsWhollyKnown() {
Expand Down Expand Up @@ -582,7 +594,7 @@ var TransposeFunc = function.New(&function.Spec{
}

for outKey, outVal := range tmpMap {
var values []cty.Value
values := make([]cty.Value, 0)
for _, v := range outVal {
values = append(values, cty.StringVal(v))
}
Expand All @@ -600,7 +612,7 @@ var TransposeFunc = function.New(&function.Spec{
// ListFunc constructs a function that takes an arbitrary number of arguments
// and returns a list containing those values in the same order.
//
// Deprecated: This function is deprecated in Terraform v0.12
// This function is deprecated in Terraform v0.12
var ListFunc = function.New(&function.Spec{
Params: []function.Parameter{},
VarParam: &function.Parameter{
Expand All @@ -621,7 +633,7 @@ var ListFunc = function.New(&function.Spec{
// MapFunc constructs a function that takes an even number of arguments and
// returns a map whose elements are constructed from consecutive pairs of arguments.
//
// Deprecated: This function is deprecated in Terraform v0.12
// This function is deprecated in Terraform v0.12
var MapFunc = function.New(&function.Spec{
Params: []function.Parameter{},
VarParam: &function.Parameter{
Expand All @@ -638,74 +650,3 @@ var MapFunc = function.New(&function.Spec{
return cty.DynamicVal, fmt.Errorf("the \"map\" function was deprecated in Terraform v0.12 and is no longer available; use tomap({ ... }) syntax to write a literal map")
},
})

// Length returns the number of elements in the given collection or number of
// Unicode characters in the given string.
func Length(collection cty.Value) (cty.Value, error) {
return LengthFunc.Call([]cty.Value{collection})
}

// AllTrue returns true if all elements of the list are true. If the list is empty,
// return true.
func AllTrue(collection cty.Value) (cty.Value, error) {
return AllTrueFunc.Call([]cty.Value{collection})
}

// AnyTrue returns true if any element of the list is true. If the list is empty,
// return false.
func AnyTrue(collection cty.Value) (cty.Value, error) {
return AnyTrueFunc.Call([]cty.Value{collection})
}

// Coalesce takes any number of arguments and returns the first one that isn't empty.
func Coalesce(args ...cty.Value) (cty.Value, error) {
return CoalesceFunc.Call(args)
}

// Index finds the element index for a given value in a list.
func Index(list, value cty.Value) (cty.Value, error) {
return IndexFunc.Call([]cty.Value{list, value})
}

// List takes any number of list arguments and returns a list containing those
//
// values in the same order.
func List(args ...cty.Value) (cty.Value, error) {
return ListFunc.Call(args)
}

// Lookup performs a dynamic lookup into a map.
// There are two required arguments, map and key, plus an optional default,
// which is a value to return if no key is found in map.
func Lookup(args ...cty.Value) (cty.Value, error) {
return LookupFunc.Call(args)
}

// Map takes an even number of arguments and returns a map whose elements are constructed
// from consecutive pairs of arguments.
func Map(args ...cty.Value) (cty.Value, error) {
return MapFunc.Call(args)
}

// Matchkeys constructs a new list by taking a subset of elements from one list
// whose indexes match the corresponding indexes of values in another list.
func Matchkeys(values, keys, searchset cty.Value) (cty.Value, error) {
return MatchkeysFunc.Call([]cty.Value{values, keys, searchset})
}

// One returns either the first element of a one-element list, or null
// if given a zero-element list..
func One(list cty.Value) (cty.Value, error) {
return OneFunc.Call([]cty.Value{list})
}

// Sum adds numbers in a list, set, or tuple
func Sum(list cty.Value) (cty.Value, error) {
return SumFunc.Call([]cty.Value{list})
}

// Transpose takes a map of lists of strings and swaps the keys and values to
// produce a new map of lists of strings.
func Transpose(values cty.Value) (cty.Value, error) {
return TransposeFunc.Call([]cty.Value{values})
}
Loading

0 comments on commit a51cedd

Please sign in to comment.