Skip to content

Commit

Permalink
feat(cloudformation): add support for the length function
Browse files Browse the repository at this point in the history
  • Loading branch information
nikpivkin authored and simar7 committed Jul 25, 2023
1 parent c894f90 commit 8fbc628
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 0 deletions.
24 changes: 24 additions & 0 deletions pkg/scanners/cloudformation/parser/fn_length.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package parser

import "github.com/aquasecurity/defsec/pkg/scanners/cloudformation/cftypes"

func ResolveLength(property *Property) (*Property, bool) {
if !property.isFunction() {
return property, true
}

val := property.AsMap()["Fn::Length"]
if val.IsList() {
return property.deriveResolved(cftypes.Int, val.Len()), true
} else if val.IsMap() {
resolved, _ := val.resolveValue()

if resolved.IsList() {
return property.deriveResolved(cftypes.Int, resolved.Len()), true
}
return resolved, false
}

return property, false

}
99 changes: 99 additions & 0 deletions pkg/scanners/cloudformation/parser/fn_length_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package parser

import (
"testing"

"github.com/aquasecurity/defsec/pkg/scanners/cloudformation/cftypes"
"github.com/stretchr/testify/require"
)

func Test_ResolveLength_WhenPropIsArray(t *testing.T) {
prop := &Property{
Inner: PropertyInner{
Type: cftypes.Map,
Value: map[string]*Property{
"Fn::Length": {
Inner: PropertyInner{
Type: cftypes.List,
Value: []*Property{
{
Inner: PropertyInner{
Type: cftypes.Int,
Value: 1,
},
},
{
Inner: PropertyInner{
Type: cftypes.String,
Value: "IntParameter",
},
},
},
},
},
},
},
}
resolved, ok := ResolveIntrinsicFunc(prop)
require.True(t, ok)
require.True(t, resolved.IsInt())
require.Equal(t, 2, resolved.AsInt())
}

func Test_ResolveLength_WhenPropIsIntrinsicFunction(t *testing.T) {
fctx := &FileContext{
Parameters: map[string]*Parameter{
"SomeParameter": {
inner: parameterInner{
Type: "string",
Default: "a|b|c|d",
},
},
},
}
prop := &Property{
Inner: PropertyInner{
Type: cftypes.Map,
Value: map[string]*Property{
"Fn::Length": {
Inner: PropertyInner{
Type: cftypes.Map,
Value: map[string]*Property{
"Fn::Split": {
Inner: PropertyInner{
Type: cftypes.List,
Value: []*Property{
{
Inner: PropertyInner{
Type: cftypes.String,
Value: "|",
},
},
{
ctx: fctx,
Inner: PropertyInner{
Type: cftypes.Map,
Value: map[string]*Property{
"Ref": {
Inner: PropertyInner{
Type: cftypes.String,
Value: "SomeParameter",
},
},
},
},
},
},
},
},
},
},
},
},
},
}
resolved, ok := ResolveIntrinsicFunc(prop)
require.True(t, ok)
require.True(t, resolved.IsInt())
require.Equal(t, 4, resolved.AsInt())
}
1 change: 1 addition & 0 deletions pkg/scanners/cloudformation/parser/intrinsics.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func init() {
"Fn::And": ResolveAnd,
"Fn::Or": ResolveOr,
"Fn::Not": ResolveNot,
"Fn::Length": ResolveLength,
}
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/scanners/cloudformation/parser/property_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ func (p *Property) AsList() []*Property {
return nil
}

func (p *Property) Len() int {
return len(p.AsList())
}

func (p *Property) EqualTo(checkValue interface{}, equalityOptions ...EqualityOptions) bool {
var ignoreCase bool
for _, option := range equalityOptions {
Expand Down

0 comments on commit 8fbc628

Please sign in to comment.