diff --git a/internal/cidr/cidr.go b/internal/cidr/cidr.go index 78f3ba58..56c442ef 100755 --- a/internal/cidr/cidr.go +++ b/internal/cidr/cidr.go @@ -38,7 +38,7 @@ func isPrivate(ip net.IP) bool { } // CountAddresses calculates the number of addresses within the given CIDR. If the given -// CIDR is in fact an IP (includes no /), 1 will bne returned. If the number of addresses +// CIDR is in fact an IP (includes no /), 1 will be returned. If the number of addresses // overflows an unsigned 64-bit int, the maximum value of an unsigned 64-bit int will be // returned. func CountAddresses(inputCIDR string) uint64 { diff --git a/lib/cidr_test.rego b/lib/cidr_test.rego new file mode 100644 index 00000000..8c919a4d --- /dev/null +++ b/lib/cidr_test.rego @@ -0,0 +1,18 @@ +package lib.cidr_test + +import rego.v1 + +import data.lib.test + +uint64max = 18446744073709551615 + +test_count_addresses if { + cidr.count_addresses("*") == uint64max + cidr.count_addresses("1.2.3.4/32") == 1 +} + +test_is_public if { + cidr.is_public("*") == true + cidr.is_public("0.0.0.0/0") == true + cidr.is_public("10.0.0.0/16") == false +} diff --git a/lib/sh/sh_test.rego b/lib/sh/sh_test.rego index a2fcffc4..10f55c96 100644 --- a/lib/sh/sh_test.rego +++ b/lib/sh/sh_test.rego @@ -1,4 +1,4 @@ -package lib.sh +package lib.sh_test test_parse_commands_with_ampersands { cmds := sh.parse_commands("apt update && apt install curl") diff --git a/lib/squealer_test.rego b/lib/squealer_test.rego new file mode 100644 index 00000000..74531135 --- /dev/null +++ b/lib/squealer_test.rego @@ -0,0 +1,15 @@ +package lib.squealer_test + +import rego.v1 + +import data.lib.test + +test_squealer_secret_not_found if { + res := squealer.scan_string(`export GREETING="Hello there"`) + res.transgressionFound == false +} + +test_squealer_secret_found if { + res := squealer.scan_string(`export DATABASE_PASSWORD=\"SomeSortOfPassword\"`) + res.transgressionFound == true +} diff --git a/pkg/rego/builtin.go b/pkg/rego/builtin.go index d22d25a7..a46378d8 100644 --- a/pkg/rego/builtin.go +++ b/pkg/rego/builtin.go @@ -11,5 +11,8 @@ var registerOnce sync.Once func RegisterBuiltins() { registerOnce.Do(func() { opa.RegisterBuiltin1(shParseCommandsDecl, shParseCommandsImpl) + opa.RegisterBuiltin1(cidrCountAdressesDecl, cidrCountAdressesImpl) + opa.RegisterBuiltin1(cidrIsPublicDecl, cidrIsPublicImpl) + opa.RegisterBuiltin1(squealerScanStringDecl, squealerScanStringImpl) }) } diff --git a/pkg/rego/cidr.go b/pkg/rego/cidr.go new file mode 100644 index 00000000..018ac9b5 --- /dev/null +++ b/pkg/rego/cidr.go @@ -0,0 +1,45 @@ +package rego + +import ( + "fmt" + + "github.com/aquasecurity/trivy-checks/internal/cidr" + "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/rego" + "github.com/open-policy-agent/opa/topdown/builtins" + "github.com/open-policy-agent/opa/types" +) + +var cidrCountAdressesDecl = ®o.Function{ + Name: "cidr.count_addresses", + Decl: types.NewFunction(types.Args(types.S), types.N), + Description: "Count addresses", + Memoize: true, +} + +var cidrCountAdressesImpl = func(_ rego.BuiltinContext, a *ast.Term) (*ast.Term, error) { + astr, err := builtins.StringOperand(a.Value, 0) + if err != nil { + return nil, fmt.Errorf("invalid parameter type: %w", err) + } + + count := cidr.CountAddresses(string(astr)) + return ast.UIntNumberTerm(count), nil +} + +var cidrIsPublicDecl = ®o.Function{ + Name: "cidr.is_public", + Decl: types.NewFunction(types.Args(types.S), types.B), + Description: "Is public", + Memoize: true, +} + +var cidrIsPublicImpl = func(_ rego.BuiltinContext, a *ast.Term) (*ast.Term, error) { + astr, err := builtins.StringOperand(a.Value, 0) + if err != nil { + return nil, fmt.Errorf("invalid parameter type: %w", err) + } + + isPublic := cidr.IsPublic(string(astr)) + return ast.BooleanTerm(isPublic), nil +} diff --git a/pkg/rego/parse_commands.go b/pkg/rego/parse_commands.go index 6ade1362..43d3d092 100644 --- a/pkg/rego/parse_commands.go +++ b/pkg/rego/parse_commands.go @@ -19,7 +19,7 @@ var shParseCommandsDecl = ®o.Function{ Memoize: true, } -var shParseCommandsImpl = func(c rego.BuiltinContext, a *ast.Term) (*ast.Term, error) { +var shParseCommandsImpl = func(_ rego.BuiltinContext, a *ast.Term) (*ast.Term, error) { astr, err := builtins.StringOperand(a.Value, 0) if err != nil { return nil, fmt.Errorf("invalid parameter type: %w", err) diff --git a/pkg/rego/squealer.go b/pkg/rego/squealer.go new file mode 100644 index 00000000..1391963e --- /dev/null +++ b/pkg/rego/squealer.go @@ -0,0 +1,36 @@ +package rego + +import ( + "fmt" + + "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/rego" + "github.com/open-policy-agent/opa/topdown/builtins" + "github.com/open-policy-agent/opa/types" + "github.com/owenrumney/squealer/pkg/squealer" +) + +var squealerScanStringDecl = ®o.Function{ + Name: "squealer.scan_string", + Decl: types.NewFunction(types.Args(types.S), types.NewObject([]*types.StaticProperty{ + {Key: "transgressionFound", Value: types.NewBoolean()}, + {Key: "description", Value: types.NewString()}, + }, nil)), + Description: "Scan string", + Memoize: true, +} + +var squealerScanStringImpl = func(_ rego.BuiltinContext, a *ast.Term) (*ast.Term, error) { + astr, err := builtins.StringOperand(a.Value, 0) + if err != nil { + return nil, fmt.Errorf("invalid parameter type: %w", err) + } + + scanner := squealer.NewStringScanner() + result := scanner.Scan(string(astr)) + + return ast.ObjectTerm( + ast.Item(ast.StringTerm("transgressionFound"), ast.BooleanTerm(result.TransgressionFound)), + ast.Item(ast.StringTerm("description"), ast.StringTerm(result.Description)), + ), nil +}