From f6fd1cddc74266cb25860d7d7920a38857624ac8 Mon Sep 17 00:00:00 2001 From: Owen Rumney Date: Wed, 5 Oct 2022 15:11:17 +0100 Subject: [PATCH] feat: add array functions for Azure arm Signed-off-by: Owen Rumney --- pkg/scanners/azure/functions/array.go | 29 +++++ pkg/scanners/azure/functions/array_test.go | 44 +++++++ .../functions/{stringFunctions => }/base64.go | 2 +- .../{stringFunctions => }/base64_test.go | 2 +- .../functions/{stringFunctions => }/casing.go | 2 +- .../{stringFunctions => }/casing_test.go | 2 +- pkg/scanners/azure/functions/concat.go | 28 +++++ pkg/scanners/azure/functions/concat_test.go | 94 +++++++++++++++ .../{stringFunctions => }/contains.go | 2 +- .../{stringFunctions => }/contains_test.go | 2 +- pkg/scanners/azure/functions/create_array.go | 11 ++ .../azure/functions/create_array_test.go | 68 +++++++++++ .../{stringFunctions => }/data_uri.go | 2 +- .../{stringFunctions => }/data_uri_test.go | 2 +- .../functions/{stringFunctions => }/empty.go | 2 +- .../{stringFunctions => }/empty_test.go | 2 +- .../{stringFunctions => }/ends_with.go | 2 +- .../{stringFunctions => }/ends_with_test.go | 2 +- .../functions/{stringFunctions => }/first.go | 2 +- .../{stringFunctions => }/first_test.go | 2 +- .../functions/{stringFunctions => }/format.go | 2 +- .../{stringFunctions => }/format_test.go | 2 +- pkg/scanners/azure/functions/functions.go | 64 +++++----- .../functions/{stringFunctions => }/guid.go | 2 +- .../{stringFunctions => }/guid_test.go | 2 +- .../{stringFunctions => }/index_of.go | 2 +- .../{stringFunctions => }/index_of_test.go | 2 +- pkg/scanners/azure/functions/intersection.go | 76 ++++++++++++ .../azure/functions/intersection_test.go | 106 +++++++++++++++++ .../functions/{stringFunctions => }/join.go | 2 +- .../{stringFunctions => }/join_test.go | 2 +- .../functions/{stringFunctions => }/json.go | 2 +- .../{stringFunctions => }/json_test.go | 2 +- .../functions/{stringFunctions => }/last.go | 2 +- .../{stringFunctions => }/last_index_of.go | 2 +- .../last_index_of_test.go | 2 +- .../{stringFunctions => }/last_test.go | 2 +- pkg/scanners/azure/functions/length.go | 29 +++++ .../{stringFunctions => }/length_test.go | 18 ++- pkg/scanners/azure/functions/max.go | 33 ++++++ pkg/scanners/azure/functions/max_test.go | 58 +++++++++ pkg/scanners/azure/functions/min.go | 33 ++++++ pkg/scanners/azure/functions/min_test.go | 58 +++++++++ .../functions/{stringFunctions => }/pad.go | 2 +- .../{stringFunctions => }/pad_test.go | 2 +- pkg/scanners/azure/functions/range.go | 30 +++++ pkg/scanners/azure/functions/range_test.go | 47 ++++++++ .../{stringFunctions => }/replace.go | 2 +- .../{stringFunctions => }/replace_test.go | 2 +- pkg/scanners/azure/functions/skip.go | 34 ++++++ .../{stringFunctions => }/skip_test.go | 20 +++- .../functions/{stringFunctions => }/split.go | 2 +- .../{stringFunctions => }/split_test.go | 2 +- .../{stringFunctions => }/starts_with.go | 2 +- .../{stringFunctions => }/starts_with_test.go | 2 +- .../functions/{stringFunctions => }/string.go | 2 +- .../azure/functions/stringFunctions/concat.go | 15 --- .../functions/stringFunctions/concat_test.go | 53 --------- .../azure/functions/stringFunctions/length.go | 15 --- .../azure/functions/stringFunctions/skip.go | 23 ---- .../azure/functions/stringFunctions/take.go | 27 ----- .../{stringFunctions => }/string_test.go | 2 +- .../{stringFunctions => }/substring.go | 2 +- .../{stringFunctions => }/substring_test.go | 2 +- pkg/scanners/azure/functions/take.go | 49 ++++++++ .../{stringFunctions => }/take_test.go | 18 ++- .../functions/{stringFunctions => }/trim.go | 2 +- .../{stringFunctions => }/trim_test.go | 2 +- pkg/scanners/azure/functions/union.go | 60 ++++++++++ pkg/scanners/azure/functions/union_test.go | 110 ++++++++++++++++++ .../{stringFunctions => }/unique_string.go | 2 +- .../unique_string_test.go | 2 +- .../functions/{stringFunctions => }/uri.go | 2 +- .../{stringFunctions => }/uri_test.go | 2 +- 74 files changed, 1130 insertions(+), 212 deletions(-) create mode 100644 pkg/scanners/azure/functions/array.go create mode 100644 pkg/scanners/azure/functions/array_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/base64.go (97%) rename pkg/scanners/azure/functions/{stringFunctions => }/base64_test.go (98%) rename pkg/scanners/azure/functions/{stringFunctions => }/casing.go (93%) rename pkg/scanners/azure/functions/{stringFunctions => }/casing_test.go (97%) create mode 100644 pkg/scanners/azure/functions/concat.go create mode 100644 pkg/scanners/azure/functions/concat_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/contains.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/contains_test.go (98%) create mode 100644 pkg/scanners/azure/functions/create_array.go create mode 100644 pkg/scanners/azure/functions/create_array_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/data_uri.go (95%) rename pkg/scanners/azure/functions/{stringFunctions => }/data_uri_test.go (97%) rename pkg/scanners/azure/functions/{stringFunctions => }/empty.go (95%) rename pkg/scanners/azure/functions/{stringFunctions => }/empty_test.go (97%) rename pkg/scanners/azure/functions/{stringFunctions => }/ends_with.go (92%) rename pkg/scanners/azure/functions/{stringFunctions => }/ends_with_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/first.go (95%) rename pkg/scanners/azure/functions/{stringFunctions => }/first_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/format.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/format_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/guid.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/guid_test.go (95%) rename pkg/scanners/azure/functions/{stringFunctions => }/index_of.go (92%) rename pkg/scanners/azure/functions/{stringFunctions => }/index_of_test.go (96%) create mode 100644 pkg/scanners/azure/functions/intersection.go create mode 100644 pkg/scanners/azure/functions/intersection_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/join.go (91%) rename pkg/scanners/azure/functions/{stringFunctions => }/join_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/json.go (92%) rename pkg/scanners/azure/functions/{stringFunctions => }/json_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/last.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/last_index_of.go (92%) rename pkg/scanners/azure/functions/{stringFunctions => }/last_index_of_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/last_test.go (96%) create mode 100644 pkg/scanners/azure/functions/length.go rename pkg/scanners/azure/functions/{stringFunctions => }/length_test.go (66%) create mode 100644 pkg/scanners/azure/functions/max.go create mode 100644 pkg/scanners/azure/functions/max_test.go create mode 100644 pkg/scanners/azure/functions/min.go create mode 100644 pkg/scanners/azure/functions/min_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/pad.go (94%) rename pkg/scanners/azure/functions/{stringFunctions => }/pad_test.go (97%) create mode 100644 pkg/scanners/azure/functions/range.go create mode 100644 pkg/scanners/azure/functions/range_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/replace.go (92%) rename pkg/scanners/azure/functions/{stringFunctions => }/replace_test.go (96%) create mode 100644 pkg/scanners/azure/functions/skip.go rename pkg/scanners/azure/functions/{stringFunctions => }/skip_test.go (67%) rename pkg/scanners/azure/functions/{stringFunctions => }/split.go (95%) rename pkg/scanners/azure/functions/{stringFunctions => }/split_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/starts_with.go (92%) rename pkg/scanners/azure/functions/{stringFunctions => }/starts_with_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/string.go (89%) delete mode 100644 pkg/scanners/azure/functions/stringFunctions/concat.go delete mode 100644 pkg/scanners/azure/functions/stringFunctions/concat_test.go delete mode 100644 pkg/scanners/azure/functions/stringFunctions/length.go delete mode 100644 pkg/scanners/azure/functions/stringFunctions/skip.go delete mode 100644 pkg/scanners/azure/functions/stringFunctions/take.go rename pkg/scanners/azure/functions/{stringFunctions => }/string_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/substring.go (94%) rename pkg/scanners/azure/functions/{stringFunctions => }/substring_test.go (96%) create mode 100644 pkg/scanners/azure/functions/take.go rename pkg/scanners/azure/functions/{stringFunctions => }/take_test.go (67%) rename pkg/scanners/azure/functions/{stringFunctions => }/trim.go (88%) rename pkg/scanners/azure/functions/{stringFunctions => }/trim_test.go (97%) create mode 100644 pkg/scanners/azure/functions/union.go create mode 100644 pkg/scanners/azure/functions/union_test.go rename pkg/scanners/azure/functions/{stringFunctions => }/unique_string.go (93%) rename pkg/scanners/azure/functions/{stringFunctions => }/unique_string_test.go (96%) rename pkg/scanners/azure/functions/{stringFunctions => }/uri.go (89%) rename pkg/scanners/azure/functions/{stringFunctions => }/uri_test.go (96%) diff --git a/pkg/scanners/azure/functions/array.go b/pkg/scanners/azure/functions/array.go new file mode 100644 index 000000000..a1da05ef4 --- /dev/null +++ b/pkg/scanners/azure/functions/array.go @@ -0,0 +1,29 @@ +package functions + +func Array(args ...interface{}) interface{} { + + if len(args) != 1 { + return "" + } + + switch ctype := args[0].(type) { + case int: + return []int{ctype} + case string: + return []string{ctype} + case map[string]interface{}: + var result []interface{} + for k, v := range ctype { + result = append(result, k, v) + } + return result + case interface{}: + switch ctype := ctype.(type) { + case []string: + return ctype + case []interface{}: + return ctype + } + } + return []interface{}{} +} diff --git a/pkg/scanners/azure/functions/array_test.go b/pkg/scanners/azure/functions/array_test.go new file mode 100644 index 000000000..c4a376ea6 --- /dev/null +++ b/pkg/scanners/azure/functions/array_test.go @@ -0,0 +1,44 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Array(t *testing.T) { + test := []struct { + name string + input []interface{} + expected interface{} + }{ + { + name: "array from an int", + input: []interface{}{1}, + expected: []int{1}, + }, + { + name: "array from a string", + input: []interface{}{"hello"}, + expected: []string{"hello"}, + }, + { + name: "array from a map", + input: []interface{}{map[string]interface{}{"hello": "world"}}, + expected: []interface{}{"hello", "world"}, + }, + { + name: "array from an slice", + input: []interface{}{ + []string{"hello", "world"}, + }, + expected: []string{"hello", "world"}, + }, + } + for _, tt := range test { + t.Run(tt.name, func(t *testing.T) { + actual := Array(tt.input...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/stringFunctions/base64.go b/pkg/scanners/azure/functions/base64.go similarity index 97% rename from pkg/scanners/azure/functions/stringFunctions/base64.go rename to pkg/scanners/azure/functions/base64.go index 421b825a1..c3222e767 100644 --- a/pkg/scanners/azure/functions/stringFunctions/base64.go +++ b/pkg/scanners/azure/functions/base64.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "encoding/base64" diff --git a/pkg/scanners/azure/functions/stringFunctions/base64_test.go b/pkg/scanners/azure/functions/base64_test.go similarity index 98% rename from pkg/scanners/azure/functions/stringFunctions/base64_test.go rename to pkg/scanners/azure/functions/base64_test.go index 95ba063f6..f557b2779 100644 --- a/pkg/scanners/azure/functions/stringFunctions/base64_test.go +++ b/pkg/scanners/azure/functions/base64_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "encoding/json" diff --git a/pkg/scanners/azure/functions/stringFunctions/casing.go b/pkg/scanners/azure/functions/casing.go similarity index 93% rename from pkg/scanners/azure/functions/stringFunctions/casing.go rename to pkg/scanners/azure/functions/casing.go index e4737fd48..56a93bbd7 100644 --- a/pkg/scanners/azure/functions/stringFunctions/casing.go +++ b/pkg/scanners/azure/functions/casing.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/casing_test.go b/pkg/scanners/azure/functions/casing_test.go similarity index 97% rename from pkg/scanners/azure/functions/stringFunctions/casing_test.go rename to pkg/scanners/azure/functions/casing_test.go index 79115d36d..51c970e17 100644 --- a/pkg/scanners/azure/functions/stringFunctions/casing_test.go +++ b/pkg/scanners/azure/functions/casing_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/concat.go b/pkg/scanners/azure/functions/concat.go new file mode 100644 index 000000000..800db04be --- /dev/null +++ b/pkg/scanners/azure/functions/concat.go @@ -0,0 +1,28 @@ +package functions + +import ( + "fmt" +) + +func Concat(args ...interface{}) interface{} { + + switch args[0].(type) { + case string: + var result string + for _, arg := range args { + result += fmt.Sprintf("%v", arg) + } + return result + case interface{}: + var result []interface{} + for _, arg := range args { + argArr, ok := arg.([]interface{}) + if !ok { + continue + } + result = append(result, argArr...) + } + return result + } + return "" +} diff --git a/pkg/scanners/azure/functions/concat_test.go b/pkg/scanners/azure/functions/concat_test.go new file mode 100644 index 000000000..7b0c461c9 --- /dev/null +++ b/pkg/scanners/azure/functions/concat_test.go @@ -0,0 +1,94 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_StringConcatenation(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected string + }{ + { + name: "simple string concatenation", + args: []interface{}{ + "hello", + ", ", + "world", + "!", + }, + expected: "hello, world!", + }, + { + name: "string concatenation with non strings", + args: []interface{}{ + "pi to 3 decimal places is ", + 3.142, + }, + expected: "pi to 3 decimal places is 3.142", + }, + { + name: "string concatenation with multiple primitives", + args: []interface{}{ + "to say that ", + 3, + " is greater than ", + 5, + " would be ", + false, + }, + expected: "to say that 3 is greater than 5 would be false", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + concatenated := Concat(tt.args...) + require.Equal(t, tt.expected, concatenated) + }) + } +} + +func Test_ArrayConcatenation(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected []interface{} + }{ + { + name: "simple array concatenation", + args: []interface{}{ + []interface{}{1, 2, 3}, + []interface{}{4, 5, 6}, + }, + expected: []interface{}{1, 2, 3, 4, 5, 6}, + }, + { + name: "array concatenation with non arrays", + args: []interface{}{ + []interface{}{1, 2, 3}, + 4, + }, + expected: []interface{}{1, 2, 3}, + }, + { + name: "array concatenation with multiple primitives", + args: []interface{}{ + []interface{}{1, 2, 3}, + 4, + []interface{}{5, 6, 7}, + }, + expected: []interface{}{1, 2, 3, 5, 6, 7}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + concatenated := Concat(tt.args...) + require.Equal(t, tt.expected, concatenated) + }) + } +} diff --git a/pkg/scanners/azure/functions/stringFunctions/contains.go b/pkg/scanners/azure/functions/contains.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/contains.go rename to pkg/scanners/azure/functions/contains.go index b655b073d..a067d63df 100644 --- a/pkg/scanners/azure/functions/stringFunctions/contains.go +++ b/pkg/scanners/azure/functions/contains.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "fmt" diff --git a/pkg/scanners/azure/functions/stringFunctions/contains_test.go b/pkg/scanners/azure/functions/contains_test.go similarity index 98% rename from pkg/scanners/azure/functions/stringFunctions/contains_test.go rename to pkg/scanners/azure/functions/contains_test.go index eb0e3da5f..e92f08fd5 100644 --- a/pkg/scanners/azure/functions/stringFunctions/contains_test.go +++ b/pkg/scanners/azure/functions/contains_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/create_array.go b/pkg/scanners/azure/functions/create_array.go new file mode 100644 index 000000000..99f355884 --- /dev/null +++ b/pkg/scanners/azure/functions/create_array.go @@ -0,0 +1,11 @@ +package functions + +func CreateArray(args ...interface{}) interface{} { + var result []interface{} + if len(args) == 0 { + return result + } + + result = append(result, args...) + return result +} diff --git a/pkg/scanners/azure/functions/create_array_test.go b/pkg/scanners/azure/functions/create_array_test.go new file mode 100644 index 000000000..5e6307488 --- /dev/null +++ b/pkg/scanners/azure/functions/create_array_test.go @@ -0,0 +1,68 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_CreateArray(t *testing.T) { + + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + { + name: "create array with strings", + args: []interface{}{ + "Hello", + "World", + }, + expected: []interface{}{"Hello", "World"}, + }, + { + name: "create array with ints", + + args: []interface{}{ + 1, 2, 3, + }, + expected: []interface{}{1, 2, 3}, + }, + { + name: "create array with arrays", + args: []interface{}{ + []interface{}{1, 2, 3}, + []interface{}{4, 5, 6}, + }, + expected: []interface{}{[]interface{}{1, 2, 3}, []interface{}{4, 5, 6}}, + }, + { + name: "create arrau with maps", + args: []interface{}{ + map[string]interface{}{ + "one": "a", + }, + map[string]interface{}{ + "two": "b", + }, + }, + expected: []interface{}{ + map[string]interface{}{ + "one": "a", + }, + map[string]interface{}{ + "two": "b", + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := CreateArray(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } + +} diff --git a/pkg/scanners/azure/functions/stringFunctions/data_uri.go b/pkg/scanners/azure/functions/data_uri.go similarity index 95% rename from pkg/scanners/azure/functions/stringFunctions/data_uri.go rename to pkg/scanners/azure/functions/data_uri.go index e4696dcdd..50f0835ee 100644 --- a/pkg/scanners/azure/functions/stringFunctions/data_uri.go +++ b/pkg/scanners/azure/functions/data_uri.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "fmt" diff --git a/pkg/scanners/azure/functions/stringFunctions/data_uri_test.go b/pkg/scanners/azure/functions/data_uri_test.go similarity index 97% rename from pkg/scanners/azure/functions/stringFunctions/data_uri_test.go rename to pkg/scanners/azure/functions/data_uri_test.go index 2d470d5cc..04f92249e 100644 --- a/pkg/scanners/azure/functions/stringFunctions/data_uri_test.go +++ b/pkg/scanners/azure/functions/data_uri_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/empty.go b/pkg/scanners/azure/functions/empty.go similarity index 95% rename from pkg/scanners/azure/functions/stringFunctions/empty.go rename to pkg/scanners/azure/functions/empty.go index 5fc130c92..1dbe8396f 100644 --- a/pkg/scanners/azure/functions/stringFunctions/empty.go +++ b/pkg/scanners/azure/functions/empty.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions func Empty(args ...interface{}) interface{} { diff --git a/pkg/scanners/azure/functions/stringFunctions/empty_test.go b/pkg/scanners/azure/functions/empty_test.go similarity index 97% rename from pkg/scanners/azure/functions/stringFunctions/empty_test.go rename to pkg/scanners/azure/functions/empty_test.go index 7c61fd34f..a21fb96cd 100644 --- a/pkg/scanners/azure/functions/stringFunctions/empty_test.go +++ b/pkg/scanners/azure/functions/empty_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/ends_with.go b/pkg/scanners/azure/functions/ends_with.go similarity index 92% rename from pkg/scanners/azure/functions/stringFunctions/ends_with.go rename to pkg/scanners/azure/functions/ends_with.go index a441d0db1..2bcd66217 100644 --- a/pkg/scanners/azure/functions/stringFunctions/ends_with.go +++ b/pkg/scanners/azure/functions/ends_with.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/ends_with_test.go b/pkg/scanners/azure/functions/ends_with_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/ends_with_test.go rename to pkg/scanners/azure/functions/ends_with_test.go index 8331f3d50..b1d1900ba 100644 --- a/pkg/scanners/azure/functions/stringFunctions/ends_with_test.go +++ b/pkg/scanners/azure/functions/ends_with_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/first.go b/pkg/scanners/azure/functions/first.go similarity index 95% rename from pkg/scanners/azure/functions/stringFunctions/first.go rename to pkg/scanners/azure/functions/first.go index 1944d64ae..3415b453f 100644 --- a/pkg/scanners/azure/functions/stringFunctions/first.go +++ b/pkg/scanners/azure/functions/first.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions func First(args ...interface{}) interface{} { if len(args) != 1 { diff --git a/pkg/scanners/azure/functions/stringFunctions/first_test.go b/pkg/scanners/azure/functions/first_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/first_test.go rename to pkg/scanners/azure/functions/first_test.go index e9a09128f..5ce059750 100644 --- a/pkg/scanners/azure/functions/stringFunctions/first_test.go +++ b/pkg/scanners/azure/functions/first_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/format.go b/pkg/scanners/azure/functions/format.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/format.go rename to pkg/scanners/azure/functions/format.go index f8f8556f7..207b9ebfd 100644 --- a/pkg/scanners/azure/functions/stringFunctions/format.go +++ b/pkg/scanners/azure/functions/format.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "fmt" diff --git a/pkg/scanners/azure/functions/stringFunctions/format_test.go b/pkg/scanners/azure/functions/format_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/format_test.go rename to pkg/scanners/azure/functions/format_test.go index 36f656891..8d5e840c6 100644 --- a/pkg/scanners/azure/functions/stringFunctions/format_test.go +++ b/pkg/scanners/azure/functions/format_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/functions.go b/pkg/scanners/azure/functions/functions.go index 1ca537d0b..81df40e5c 100644 --- a/pkg/scanners/azure/functions/functions.go +++ b/pkg/scanners/azure/functions/functions.go @@ -1,7 +1,5 @@ package functions -import "github.com/aquasecurity/defsec/pkg/scanners/azure/functions/stringFunctions" - var deploymentFuncs = map[string]func(dp DeploymentData, args ...interface{}) interface{}{ "parameters": Parameters, "deployment": Deployment, @@ -10,33 +8,41 @@ var deploymentFuncs = map[string]func(dp DeploymentData, args ...interface{}) in } var generalFuncs = map[string]func(...interface{}) interface{}{ - "base64": stringFunctions.Base64, - "base64ToJson": stringFunctions.Base64ToJson, - "concat": stringFunctions.Concat, - "contains": stringFunctions.Contains, - "dataUri": stringFunctions.DataUri, - "dataUriToString": stringFunctions.DataUriToString, - "empty": stringFunctions.Empty, - "endsWith": stringFunctions.EndsWith, - "format": stringFunctions.Format, - "guid": stringFunctions.Guid, - "indexOf": stringFunctions.IndexOf, - "join": stringFunctions.Join, - "lastIndexOf": stringFunctions.LastIndexOf, - "length": stringFunctions.Length, - "newGuid": stringFunctions.NewGuid, - "padLeft": stringFunctions.PadLeft, - "replace": stringFunctions.Replace, - "skip": stringFunctions.Skip, - "split": stringFunctions.Split, - "startsWith": stringFunctions.StartsWith, - "string": stringFunctions.String, - "substring": stringFunctions.SubString, - "toLower": stringFunctions.ToLower, - "toUpper": stringFunctions.ToUpper, - "trim": stringFunctions.Trim, - "uniqueString": stringFunctions.UniqueString, - "uri": stringFunctions.Uri, + "array": Array, + "base64": Base64, + "base64ToJson": Base64ToJson, + "concat": Concat, + "contains": Contains, + "createArray": CreateArray, + "dataUri": DataUri, + "dataUriToString": DataUriToString, + "empty": Empty, + "endsWith": EndsWith, + "format": Format, + "guid": Guid, + "indexOf": IndexOf, + "intersection": Intersection, + "join": Join, + "lastIndexOf": LastIndexOf, + "length": Length, + "max": Max, + "min": Min, + "newGuid": NewGuid, + "padLeft": PadLeft, + "range": Range, + "replace": Replace, + "skip": Skip, + "split": Split, + "startsWith": StartsWith, + "string": String, + "substring": SubString, + "toLower": ToLower, + "toUpper": ToUpper, + "trim": Trim, + "union": Union, + "union:": Union, + "uniqueString": UniqueString, + "uri": Uri, } func Evaluate(deploymentProvider DeploymentData, name string, args ...interface{}) interface{} { diff --git a/pkg/scanners/azure/functions/stringFunctions/guid.go b/pkg/scanners/azure/functions/guid.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/guid.go rename to pkg/scanners/azure/functions/guid.go index 3e6abbe14..d54bbacb1 100644 --- a/pkg/scanners/azure/functions/stringFunctions/guid.go +++ b/pkg/scanners/azure/functions/guid.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "crypto/sha256" diff --git a/pkg/scanners/azure/functions/stringFunctions/guid_test.go b/pkg/scanners/azure/functions/guid_test.go similarity index 95% rename from pkg/scanners/azure/functions/stringFunctions/guid_test.go rename to pkg/scanners/azure/functions/guid_test.go index 6abd62a9a..0e47e5383 100644 --- a/pkg/scanners/azure/functions/stringFunctions/guid_test.go +++ b/pkg/scanners/azure/functions/guid_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/index_of.go b/pkg/scanners/azure/functions/index_of.go similarity index 92% rename from pkg/scanners/azure/functions/stringFunctions/index_of.go rename to pkg/scanners/azure/functions/index_of.go index eb85123a8..93896e21e 100644 --- a/pkg/scanners/azure/functions/stringFunctions/index_of.go +++ b/pkg/scanners/azure/functions/index_of.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/index_of_test.go b/pkg/scanners/azure/functions/index_of_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/index_of_test.go rename to pkg/scanners/azure/functions/index_of_test.go index 91fcd10c7..c35d59279 100644 --- a/pkg/scanners/azure/functions/stringFunctions/index_of_test.go +++ b/pkg/scanners/azure/functions/index_of_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/intersection.go b/pkg/scanners/azure/functions/intersection.go new file mode 100644 index 000000000..5eace2fe0 --- /dev/null +++ b/pkg/scanners/azure/functions/intersection.go @@ -0,0 +1,76 @@ +package functions + +import "sort" + +func Intersection(args ...interface{}) interface{} { + + if args == nil || len(args) < 2 { + return []interface{}{} + } + + switch args[0].(type) { + case map[string]interface{}: + return intersectionMap(args...) + case interface{}: + return intersectionArray(args...) + } + + return []interface{}{} +} + +func intersectionArray(args ...interface{}) interface{} { + result := []interface{}{} + hash := make(map[interface{}]bool) + + for _, arg := range args[0].([]interface{}) { + hash[arg] = true + } + + for i := 1; i < len(args); i++ { + workingHash := make(map[interface{}]bool) + argArr, ok := args[i].([]interface{}) + if !ok { + continue + } + for _, item := range argArr { + if _, ok := hash[item]; ok { + workingHash[item] = true + } + } + hash = workingHash + } + + for k := range hash { + result = append(result, k) + } + + sort.Slice(result, func(i, j int) bool { + return result[i].(string) < result[j].(string) + }) + + return result +} + +func intersectionMap(args ...interface{}) interface{} { + hash := make(map[string]interface{}) + + for k, v := range args[0].(map[string]interface{}) { + hash[k] = v + } + + for i := 1; i < len(args); i++ { + workingHash := make(map[string]interface{}) + argArr, ok := args[i].(map[string]interface{}) + if !ok { + continue + } + for k, v := range argArr { + if ev, ok := hash[k]; ok && ev == v { + workingHash[k] = v + } + } + hash = workingHash + } + + return hash +} diff --git a/pkg/scanners/azure/functions/intersection_test.go b/pkg/scanners/azure/functions/intersection_test.go new file mode 100644 index 000000000..98630fa96 --- /dev/null +++ b/pkg/scanners/azure/functions/intersection_test.go @@ -0,0 +1,106 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Intersect(t *testing.T) { + + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + { + name: "intersect two arrays", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + []interface{}{"b", "c", "d"}, + }, + expected: []interface{}{"b", "c"}, + }, + { + name: "intersect three arrays", + args: []interface{}{ + []interface{}{"a", "b", "c", "d"}, + []interface{}{"b", "c", "d"}, + []interface{}{"b", "c"}, + }, + expected: []interface{}{"b", "c"}, + }, + { + name: "intersect two arrays with one empty", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + []interface{}{}, + }, + expected: []interface{}{}, + }, + { + name: "intersect two arrays with both empty", + args: []interface{}{ + []interface{}{}, + []interface{}{}, + }, + expected: []interface{}{}, + }, + { + name: "intersect two arrays with both nil", + args: []interface{}{ + nil, + nil, + }, + expected: []interface{}{}, + }, + { + name: "intersect two maps", + args: []interface{}{ + map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + }, + map[string]interface{}{ + "b": "b", + "c": "c", + "d": "d", + }, + }, + expected: map[string]interface{}{ + "b": "b", + "c": "c", + }, + }, + { + name: "intersect three maps", + args: []interface{}{ + map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + }, + map[string]interface{}{ + "b": "b", + "c": "c", + "d": "d", + }, + map[string]interface{}{ + "b": "b", + "d": "d", + }, + }, + expected: map[string]interface{}{ + "b": "b", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Intersection(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/stringFunctions/join.go b/pkg/scanners/azure/functions/join.go similarity index 91% rename from pkg/scanners/azure/functions/stringFunctions/join.go rename to pkg/scanners/azure/functions/join.go index 21d44f260..cdefa43fd 100644 --- a/pkg/scanners/azure/functions/stringFunctions/join.go +++ b/pkg/scanners/azure/functions/join.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/join_test.go b/pkg/scanners/azure/functions/join_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/join_test.go rename to pkg/scanners/azure/functions/join_test.go index 7e9e1b17d..fab50a4e1 100644 --- a/pkg/scanners/azure/functions/stringFunctions/join_test.go +++ b/pkg/scanners/azure/functions/join_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/json.go b/pkg/scanners/azure/functions/json.go similarity index 92% rename from pkg/scanners/azure/functions/stringFunctions/json.go rename to pkg/scanners/azure/functions/json.go index 5ad96cdae..7694b3587 100644 --- a/pkg/scanners/azure/functions/stringFunctions/json.go +++ b/pkg/scanners/azure/functions/json.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "encoding/json" diff --git a/pkg/scanners/azure/functions/stringFunctions/json_test.go b/pkg/scanners/azure/functions/json_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/json_test.go rename to pkg/scanners/azure/functions/json_test.go index 9248a5406..1f04cd650 100644 --- a/pkg/scanners/azure/functions/stringFunctions/json_test.go +++ b/pkg/scanners/azure/functions/json_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/last.go b/pkg/scanners/azure/functions/last.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/last.go rename to pkg/scanners/azure/functions/last.go index 3a65da722..8466ec6b6 100644 --- a/pkg/scanners/azure/functions/stringFunctions/last.go +++ b/pkg/scanners/azure/functions/last.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions func Last(args ...interface{}) interface{} { if len(args) != 1 { diff --git a/pkg/scanners/azure/functions/stringFunctions/last_index_of.go b/pkg/scanners/azure/functions/last_index_of.go similarity index 92% rename from pkg/scanners/azure/functions/stringFunctions/last_index_of.go rename to pkg/scanners/azure/functions/last_index_of.go index cb79e2316..7dce6320d 100644 --- a/pkg/scanners/azure/functions/stringFunctions/last_index_of.go +++ b/pkg/scanners/azure/functions/last_index_of.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/last_index_of_test.go b/pkg/scanners/azure/functions/last_index_of_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/last_index_of_test.go rename to pkg/scanners/azure/functions/last_index_of_test.go index 6fda5d426..96b78d72d 100644 --- a/pkg/scanners/azure/functions/stringFunctions/last_index_of_test.go +++ b/pkg/scanners/azure/functions/last_index_of_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/last_test.go b/pkg/scanners/azure/functions/last_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/last_test.go rename to pkg/scanners/azure/functions/last_test.go index fbceec3f0..2ceafbf8a 100644 --- a/pkg/scanners/azure/functions/stringFunctions/last_test.go +++ b/pkg/scanners/azure/functions/last_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/length.go b/pkg/scanners/azure/functions/length.go new file mode 100644 index 000000000..d74bfb255 --- /dev/null +++ b/pkg/scanners/azure/functions/length.go @@ -0,0 +1,29 @@ +package functions + +func Length(args ...interface{}) interface{} { + + if len(args) != 1 { + return 0 + } + + switch ctype := args[0].(type) { + case string: + return len(ctype) + case map[string]interface{}: + return len(ctype) + case interface{}: + switch iType := ctype.(type) { + case []string: + return len(iType) + case []bool: + return len(iType) + case []int: + return len(iType) + case []float64: + return len(iType) + case []interface{}: + return len(iType) + } + } + return 0 +} diff --git a/pkg/scanners/azure/functions/stringFunctions/length_test.go b/pkg/scanners/azure/functions/length_test.go similarity index 66% rename from pkg/scanners/azure/functions/stringFunctions/length_test.go rename to pkg/scanners/azure/functions/length_test.go index e73a26e6c..2d15ba496 100644 --- a/pkg/scanners/azure/functions/stringFunctions/length_test.go +++ b/pkg/scanners/azure/functions/length_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" @@ -27,6 +27,22 @@ func Test_Length(t *testing.T) { }, expected: 0, }, + { + name: "length of an empty slice", + args: []interface{}{ + []string{}, + }, + expected: 0, + }, + { + name: "length of an slice with items", + args: []interface{}{ + []string{ + "hello", "world", + }, + }, + expected: 2, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/scanners/azure/functions/max.go b/pkg/scanners/azure/functions/max.go new file mode 100644 index 000000000..6cbfd5ba2 --- /dev/null +++ b/pkg/scanners/azure/functions/max.go @@ -0,0 +1,33 @@ +package functions + +func Max(args ...interface{}) interface{} { + switch args[0].(type) { + case int: + var ints []int + for _, arg := range args { + ints = append(ints, arg.(int)) + } + return maxInt(ints) + case interface{}: + switch iType := args[0].(type) { + case []int: + return maxInt(iType) + } + } + return 0 +} + +func maxInt(args []int) int { + if len(args) == 0 { + return 0 + } + + max := args[0] + + for i := 1; i < len(args); i++ { + if args[i] > max { + max = args[i] + } + } + return max +} diff --git a/pkg/scanners/azure/functions/max_test.go b/pkg/scanners/azure/functions/max_test.go new file mode 100644 index 000000000..942fad7e9 --- /dev/null +++ b/pkg/scanners/azure/functions/max_test.go @@ -0,0 +1,58 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Max(t *testing.T) { + test := []struct { + name string + args []interface{} + expected int + }{ + { + name: "max of empty slice", + args: []interface{}{ + []int{}, + }, + expected: 0, + }, + { + name: "max of slice", + args: []interface{}{ + []int{1, 2, 3}, + }, + expected: 3, + }, + { + name: "max of slice with negative numbers", + args: []interface{}{ + []int{-1, -2, -3}, + }, + expected: -1, + }, + { + name: "max of slice with negative and positive numbers", + args: []interface{}{ + []int{-1, 2, -3}, + }, + expected: 2, + }, + { + name: "max of comma separated numbers", + args: []interface{}{ + 1, 2, 3, 4, 5, + }, + expected: 5, + }, + } + + for _, tt := range test { + t.Run(tt.name, func(t *testing.T) { + actual := Max(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/min.go b/pkg/scanners/azure/functions/min.go new file mode 100644 index 000000000..35900e26d --- /dev/null +++ b/pkg/scanners/azure/functions/min.go @@ -0,0 +1,33 @@ +package functions + +func Min(args ...interface{}) interface{} { + switch args[0].(type) { + case int: + var ints []int + for _, arg := range args { + ints = append(ints, arg.(int)) + } + return minInt(ints) + case interface{}: + switch iType := args[0].(type) { + case []int: + return minInt(iType) + } + } + return 0 +} + +func minInt(args []int) int { + if len(args) == 0 { + return 0 + } + + min := args[0] + + for i := 1; i < len(args); i++ { + if args[i] < min { + min = args[i] + } + } + return min +} diff --git a/pkg/scanners/azure/functions/min_test.go b/pkg/scanners/azure/functions/min_test.go new file mode 100644 index 000000000..28e12ef69 --- /dev/null +++ b/pkg/scanners/azure/functions/min_test.go @@ -0,0 +1,58 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Min(t *testing.T) { + test := []struct { + name string + args []interface{} + expected int + }{ + { + name: "min of empty slice", + args: []interface{}{ + []int{}, + }, + expected: 0, + }, + { + name: "min of slice", + args: []interface{}{ + []int{1, 2, 3}, + }, + expected: 1, + }, + { + name: "min of slice with negative numbers", + args: []interface{}{ + []int{-1, -2, -3}, + }, + expected: -3, + }, + { + name: "min of slice with negative and positive numbers", + args: []interface{}{ + []int{-1, 2, -3}, + }, + expected: -3, + }, + { + name: "min of comma separated numbers", + args: []interface{}{ + 1, 2, 3, 4, 5, + }, + expected: 1, + }, + } + + for _, tt := range test { + t.Run(tt.name, func(t *testing.T) { + actual := Min(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/stringFunctions/pad.go b/pkg/scanners/azure/functions/pad.go similarity index 94% rename from pkg/scanners/azure/functions/stringFunctions/pad.go rename to pkg/scanners/azure/functions/pad.go index cdb1bb1ee..9d668210b 100644 --- a/pkg/scanners/azure/functions/stringFunctions/pad.go +++ b/pkg/scanners/azure/functions/pad.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/pad_test.go b/pkg/scanners/azure/functions/pad_test.go similarity index 97% rename from pkg/scanners/azure/functions/stringFunctions/pad_test.go rename to pkg/scanners/azure/functions/pad_test.go index d4c51ced1..e7d274504 100644 --- a/pkg/scanners/azure/functions/stringFunctions/pad_test.go +++ b/pkg/scanners/azure/functions/pad_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/range.go b/pkg/scanners/azure/functions/range.go new file mode 100644 index 000000000..12a352695 --- /dev/null +++ b/pkg/scanners/azure/functions/range.go @@ -0,0 +1,30 @@ +package functions + +func Range(args ...interface{}) interface{} { + + if len(args) != 2 { + return []interface{}{} + } + + start, ok := args[0].(int) + if !ok { + return []int{} + } + + count, ok := args[1].(int) + if !ok { + return []int{} + } + + if count > 10000 { + count = 10000 + } + + result := make([]int, count) + + for i := 0; i < count; i++ { + result[i] = start + i + } + + return result +} diff --git a/pkg/scanners/azure/functions/range_test.go b/pkg/scanners/azure/functions/range_test.go new file mode 100644 index 000000000..9c0c6a084 --- /dev/null +++ b/pkg/scanners/azure/functions/range_test.go @@ -0,0 +1,47 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Range(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + { + name: "range for 3 from 1", + args: []interface{}{ + 1, + 3, + }, + expected: []int{1, 2, 3}, + }, + { + name: "range with for 10 from 3", + args: []interface{}{ + 3, + 10, + }, + expected: []int{3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + }, + { + name: "range with for 10 from -10", + args: []interface{}{ + -10, + 10, + }, + expected: []int{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Range(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } + +} diff --git a/pkg/scanners/azure/functions/stringFunctions/replace.go b/pkg/scanners/azure/functions/replace.go similarity index 92% rename from pkg/scanners/azure/functions/stringFunctions/replace.go rename to pkg/scanners/azure/functions/replace.go index 50b273779..00a7a8a45 100644 --- a/pkg/scanners/azure/functions/stringFunctions/replace.go +++ b/pkg/scanners/azure/functions/replace.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/replace_test.go b/pkg/scanners/azure/functions/replace_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/replace_test.go rename to pkg/scanners/azure/functions/replace_test.go index 245a772fe..fe8fb4099 100644 --- a/pkg/scanners/azure/functions/stringFunctions/replace_test.go +++ b/pkg/scanners/azure/functions/replace_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/skip.go b/pkg/scanners/azure/functions/skip.go new file mode 100644 index 000000000..b68296fff --- /dev/null +++ b/pkg/scanners/azure/functions/skip.go @@ -0,0 +1,34 @@ +package functions + +func Skip(args ...interface{}) interface{} { + if len(args) != 2 { + return "" + } + + count, ok := args[1].(int) + if !ok { + return "" + } + switch input := args[0].(type) { + case string: + if count > len(input) { + return "" + } + return input[count:] + case interface{}: + switch iType := input.(type) { + case []int: + return iType[count:] + case []string: + return iType[count:] + case []bool: + return iType[count:] + case []float64: + return iType[count:] + case []interface{}: + return iType[count:] + } + } + + return "" +} diff --git a/pkg/scanners/azure/functions/stringFunctions/skip_test.go b/pkg/scanners/azure/functions/skip_test.go similarity index 67% rename from pkg/scanners/azure/functions/stringFunctions/skip_test.go rename to pkg/scanners/azure/functions/skip_test.go index 15785e36a..692e6508f 100644 --- a/pkg/scanners/azure/functions/stringFunctions/skip_test.go +++ b/pkg/scanners/azure/functions/skip_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" @@ -11,7 +11,7 @@ func Test_Skip(t *testing.T) { tests := []struct { name string args []interface{} - expected string + expected interface{} }{ { name: "skip a string", @@ -37,6 +37,22 @@ func Test_Skip(t *testing.T) { }, expected: "hello", }, + { + name: "skip with slice of ints", + args: []interface{}{ + []int{1, 2, 3, 4, 5}, + 2, + }, + expected: []int{3, 4, 5}, + }, + { + name: "skip with slice of strings", + args: []interface{}{ + []string{"hello", "world"}, + 1, + }, + expected: []string{"world"}, + }, } for _, tt := range tests { diff --git a/pkg/scanners/azure/functions/stringFunctions/split.go b/pkg/scanners/azure/functions/split.go similarity index 95% rename from pkg/scanners/azure/functions/stringFunctions/split.go rename to pkg/scanners/azure/functions/split.go index 1fb604265..04b7f5779 100644 --- a/pkg/scanners/azure/functions/stringFunctions/split.go +++ b/pkg/scanners/azure/functions/split.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/split_test.go b/pkg/scanners/azure/functions/split_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/split_test.go rename to pkg/scanners/azure/functions/split_test.go index 311cceb46..e40df0752 100644 --- a/pkg/scanners/azure/functions/stringFunctions/split_test.go +++ b/pkg/scanners/azure/functions/split_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/starts_with.go b/pkg/scanners/azure/functions/starts_with.go similarity index 92% rename from pkg/scanners/azure/functions/stringFunctions/starts_with.go rename to pkg/scanners/azure/functions/starts_with.go index 8767d32f7..a4eb398ce 100644 --- a/pkg/scanners/azure/functions/stringFunctions/starts_with.go +++ b/pkg/scanners/azure/functions/starts_with.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/starts_with_test.go b/pkg/scanners/azure/functions/starts_with_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/starts_with_test.go rename to pkg/scanners/azure/functions/starts_with_test.go index 97f060d18..4a745478e 100644 --- a/pkg/scanners/azure/functions/stringFunctions/starts_with_test.go +++ b/pkg/scanners/azure/functions/starts_with_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/string.go b/pkg/scanners/azure/functions/string.go similarity index 89% rename from pkg/scanners/azure/functions/stringFunctions/string.go rename to pkg/scanners/azure/functions/string.go index 602e0d966..cba9997d9 100644 --- a/pkg/scanners/azure/functions/stringFunctions/string.go +++ b/pkg/scanners/azure/functions/string.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "fmt" diff --git a/pkg/scanners/azure/functions/stringFunctions/concat.go b/pkg/scanners/azure/functions/stringFunctions/concat.go deleted file mode 100644 index 2f4db47e7..000000000 --- a/pkg/scanners/azure/functions/stringFunctions/concat.go +++ /dev/null @@ -1,15 +0,0 @@ -package stringFunctions - -import ( - "fmt" -) - -func Concat(args ...interface{}) interface{} { - var result string - - for _, arg := range args { - result += fmt.Sprintf("%v", arg) - } - - return result -} diff --git a/pkg/scanners/azure/functions/stringFunctions/concat_test.go b/pkg/scanners/azure/functions/stringFunctions/concat_test.go deleted file mode 100644 index d51ab5720..000000000 --- a/pkg/scanners/azure/functions/stringFunctions/concat_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package stringFunctions - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_Concatenation(t *testing.T) { - tests := []struct { - name string - args []interface{} - expected string - }{ - { - name: "simple string concatenation", - args: []interface{}{ - "hello", - ", ", - "world", - "!", - }, - expected: "hello, world!", - }, - { - name: "string concatenation with non strings", - args: []interface{}{ - "pi to 3 decimal places is ", - 3.142, - }, - expected: "pi to 3 decimal places is 3.142", - }, - { - name: "string concatenation with multiple primitives", - args: []interface{}{ - "to say that ", - 3, - " is greater than ", - 5, - " would be ", - false, - }, - expected: "to say that 3 is greater than 5 would be false", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - concatenated := Concat(tt.args...) - require.Equal(t, tt.expected, concatenated) - }) - } -} diff --git a/pkg/scanners/azure/functions/stringFunctions/length.go b/pkg/scanners/azure/functions/stringFunctions/length.go deleted file mode 100644 index be5181db4..000000000 --- a/pkg/scanners/azure/functions/stringFunctions/length.go +++ /dev/null @@ -1,15 +0,0 @@ -package stringFunctions - -func Length(args ...interface{}) interface{} { - - if len(args) != 1 { - return 0 - } - - input, ok := args[0].(string) - if !ok { - return 0 - } - return len(input) - -} diff --git a/pkg/scanners/azure/functions/stringFunctions/skip.go b/pkg/scanners/azure/functions/stringFunctions/skip.go deleted file mode 100644 index 2c9bc041c..000000000 --- a/pkg/scanners/azure/functions/stringFunctions/skip.go +++ /dev/null @@ -1,23 +0,0 @@ -package stringFunctions - -func Skip(args ...interface{}) interface{} { - if len(args) != 2 { - return "" - } - - input, ok := args[0].(string) - if !ok { - return "" - } - - count, ok := args[1].(int) - if !ok { - return "" - } - - if count > len(input) { - return "" - } - - return input[count:] -} diff --git a/pkg/scanners/azure/functions/stringFunctions/take.go b/pkg/scanners/azure/functions/stringFunctions/take.go deleted file mode 100644 index e7211c833..000000000 --- a/pkg/scanners/azure/functions/stringFunctions/take.go +++ /dev/null @@ -1,27 +0,0 @@ -package stringFunctions - -func Take(args ...interface{}) interface{} { - if len(args) != 2 { - return "" - } - - count, ok := args[1].(int) - if !ok { - return "" - } - - switch input := args[0].(type) { - case string: - if count > len(input) { - return input - } - return input[:count] - case []string: - if count > len(input) { - return input - } - return input[:count] - } - - return "" -} diff --git a/pkg/scanners/azure/functions/stringFunctions/string_test.go b/pkg/scanners/azure/functions/string_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/string_test.go rename to pkg/scanners/azure/functions/string_test.go index 8d27d6149..ecab50ea8 100644 --- a/pkg/scanners/azure/functions/stringFunctions/string_test.go +++ b/pkg/scanners/azure/functions/string_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/substring.go b/pkg/scanners/azure/functions/substring.go similarity index 94% rename from pkg/scanners/azure/functions/stringFunctions/substring.go rename to pkg/scanners/azure/functions/substring.go index ca5393ce9..fed22f0d1 100644 --- a/pkg/scanners/azure/functions/stringFunctions/substring.go +++ b/pkg/scanners/azure/functions/substring.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions func SubString(args ...interface{}) interface{} { if len(args) < 2 { diff --git a/pkg/scanners/azure/functions/stringFunctions/substring_test.go b/pkg/scanners/azure/functions/substring_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/substring_test.go rename to pkg/scanners/azure/functions/substring_test.go index 3bbf72dbe..56e2ea107 100644 --- a/pkg/scanners/azure/functions/stringFunctions/substring_test.go +++ b/pkg/scanners/azure/functions/substring_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/take.go b/pkg/scanners/azure/functions/take.go new file mode 100644 index 000000000..738c9d7d8 --- /dev/null +++ b/pkg/scanners/azure/functions/take.go @@ -0,0 +1,49 @@ +package functions + +func Take(args ...interface{}) interface{} { + if len(args) != 2 { + return "" + } + + count, ok := args[1].(int) + if !ok { + return "" + } + switch input := args[0].(type) { + case string: + if count > len(input) { + return input + } + return input[:count] + case interface{}: + switch iType := input.(type) { + case []int: + if count > len(iType) { + return iType + } + return iType[:count] + case []string: + if count > len(iType) { + return iType + } + return iType[:count] + case []bool: + if count > len(iType) { + return iType + } + return iType[:count] + case []float64: + if count > len(iType) { + return iType + } + return iType[:count] + case []interface{}: + if count > len(iType) { + return iType + } + return iType[:count] + } + } + + return "" +} diff --git a/pkg/scanners/azure/functions/stringFunctions/take_test.go b/pkg/scanners/azure/functions/take_test.go similarity index 67% rename from pkg/scanners/azure/functions/stringFunctions/take_test.go rename to pkg/scanners/azure/functions/take_test.go index 433540276..68c19070a 100644 --- a/pkg/scanners/azure/functions/stringFunctions/take_test.go +++ b/pkg/scanners/azure/functions/take_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" @@ -36,6 +36,22 @@ func Test_Take(t *testing.T) { }, expected: []string{"a", "b"}, }, + { + name: "take a string from a slice", + args: []interface{}{ + []string{"a", "b", "c"}, + 2, + }, + expected: []string{"a", "b"}, + }, + { + name: "take a string from a slice with invalid count", + args: []interface{}{ + []string{"a", "b", "c"}, + 10, + }, + expected: []string{"a", "b", "c"}, + }, } for _, tt := range tests { diff --git a/pkg/scanners/azure/functions/stringFunctions/trim.go b/pkg/scanners/azure/functions/trim.go similarity index 88% rename from pkg/scanners/azure/functions/stringFunctions/trim.go rename to pkg/scanners/azure/functions/trim.go index c60c465d5..5215bbe7f 100644 --- a/pkg/scanners/azure/functions/stringFunctions/trim.go +++ b/pkg/scanners/azure/functions/trim.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "strings" diff --git a/pkg/scanners/azure/functions/stringFunctions/trim_test.go b/pkg/scanners/azure/functions/trim_test.go similarity index 97% rename from pkg/scanners/azure/functions/stringFunctions/trim_test.go rename to pkg/scanners/azure/functions/trim_test.go index 7a78af3be..44a787b0f 100644 --- a/pkg/scanners/azure/functions/stringFunctions/trim_test.go +++ b/pkg/scanners/azure/functions/trim_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "testing" diff --git a/pkg/scanners/azure/functions/union.go b/pkg/scanners/azure/functions/union.go new file mode 100644 index 000000000..07bb98f28 --- /dev/null +++ b/pkg/scanners/azure/functions/union.go @@ -0,0 +1,60 @@ +package functions + +import "sort" + +func Union(args ...interface{}) interface{} { + if len(args) == 0 { + return []interface{}{} + } + if len(args) == 1 { + return args[0] + } + + switch args[0].(type) { + case map[string]interface{}: + return unionMap(args...) + case interface{}: + return unionArray(args...) + } + + return []interface{}{} + +} + +func unionMap(args ...interface{}) interface{} { + result := make(map[string]interface{}) + + for _, arg := range args { + switch iType := arg.(type) { + case map[string]interface{}: + for k, v := range iType { + result[k] = v + } + } + } + + return result +} + +func unionArray(args ...interface{}) interface{} { + result := []interface{}{} + union := make(map[interface{}]bool) + + for _, arg := range args { + switch iType := arg.(type) { + case []interface{}: + for _, item := range iType { + union[item] = true + } + } + } + + for k := range union { + result = append(result, k) + } + sort.Slice(result, func(i, j int) bool { + return result[i].(string) < result[j].(string) + }) + + return result +} diff --git a/pkg/scanners/azure/functions/union_test.go b/pkg/scanners/azure/functions/union_test.go new file mode 100644 index 000000000..56d5bf809 --- /dev/null +++ b/pkg/scanners/azure/functions/union_test.go @@ -0,0 +1,110 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Union(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + { + name: "union single array", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + }, + expected: []interface{}{"a", "b", "c"}, + }, + { + name: "union two arrays", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + []interface{}{"b", "c", "d"}, + }, + expected: []interface{}{"a", "b", "c", "d"}, + }, + { + name: "union two arrays", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + []interface{}{"b", "c", "d"}, + []interface{}{"b", "c", "d", "e"}, + }, + expected: []interface{}{"a", "b", "c", "d", "e"}, + }, + { + name: "union single maps", + args: []interface{}{ + map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + }, + }, + expected: map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + }, + }, + { + name: "union two maps", + args: []interface{}{ + map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + }, + map[string]interface{}{ + "b": "b", + "c": "c", + "d": "d", + }, + }, + expected: map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + "d": "d", + }, + }, + { + name: "union three maps", + args: []interface{}{ + map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + }, + map[string]interface{}{ + "b": "b", + "c": "c", + "d": "d", + }, + map[string]interface{}{ + "b": "b", + "c": "c", + "e": "e", + }, + }, + expected: map[string]interface{}{ + "a": "a", + "b": "b", + "c": "c", + "d": "d", + "e": "e", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Union(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/stringFunctions/unique_string.go b/pkg/scanners/azure/functions/unique_string.go similarity index 93% rename from pkg/scanners/azure/functions/stringFunctions/unique_string.go rename to pkg/scanners/azure/functions/unique_string.go index d4534a6d3..fba35c645 100644 --- a/pkg/scanners/azure/functions/stringFunctions/unique_string.go +++ b/pkg/scanners/azure/functions/unique_string.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "crypto/sha256" diff --git a/pkg/scanners/azure/functions/stringFunctions/unique_string_test.go b/pkg/scanners/azure/functions/unique_string_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/unique_string_test.go rename to pkg/scanners/azure/functions/unique_string_test.go index 8a3dc4edc..035591eb4 100644 --- a/pkg/scanners/azure/functions/stringFunctions/unique_string_test.go +++ b/pkg/scanners/azure/functions/unique_string_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing" diff --git a/pkg/scanners/azure/functions/stringFunctions/uri.go b/pkg/scanners/azure/functions/uri.go similarity index 89% rename from pkg/scanners/azure/functions/stringFunctions/uri.go rename to pkg/scanners/azure/functions/uri.go index df6b86e14..6e33a07c7 100644 --- a/pkg/scanners/azure/functions/stringFunctions/uri.go +++ b/pkg/scanners/azure/functions/uri.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import "net/url" diff --git a/pkg/scanners/azure/functions/stringFunctions/uri_test.go b/pkg/scanners/azure/functions/uri_test.go similarity index 96% rename from pkg/scanners/azure/functions/stringFunctions/uri_test.go rename to pkg/scanners/azure/functions/uri_test.go index f1e9ea38a..1839aa554 100644 --- a/pkg/scanners/azure/functions/stringFunctions/uri_test.go +++ b/pkg/scanners/azure/functions/uri_test.go @@ -1,4 +1,4 @@ -package stringFunctions +package functions import ( "testing"