Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add CIDR and squealer built-in Rego functions #174

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/cidr/cidr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
18 changes: 18 additions & 0 deletions lib/cidr_test.rego
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 1 addition & 1 deletion lib/sh/sh_test.rego
Original file line number Diff line number Diff line change
@@ -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")
Expand Down
15 changes: 15 additions & 0 deletions lib/squealer_test.rego
Original file line number Diff line number Diff line change
@@ -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
}
3 changes: 3 additions & 0 deletions pkg/rego/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}
45 changes: 45 additions & 0 deletions pkg/rego/cidr.go
Original file line number Diff line number Diff line change
@@ -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 = &rego.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 = &rego.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
}
2 changes: 1 addition & 1 deletion pkg/rego/parse_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var shParseCommandsDecl = &rego.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)
Expand Down
36 changes: 36 additions & 0 deletions pkg/rego/squealer.go
Original file line number Diff line number Diff line change
@@ -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 = &rego.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
}
Loading