Skip to content

Commit

Permalink
feat: Add external_data function to Gator Test command
Browse files Browse the repository at this point in the history
Signed-off-by: Fardin Khanjani <fardin.khanjani@tradeshift.com>
  • Loading branch information
fardin01 committed May 24, 2023
1 parent 3801633 commit 4fbc9be
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
2 changes: 1 addition & 1 deletion cmd/gator/expand/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func init() {
}

func run(cmd *cobra.Command, args []string) {
unstrucs, err := reader.ReadSources(flagFilenames, flagImages, flagTempDir)
unstrucs, err := reader.ReadSources(flagFilenames, flagImages, flagTempDir, []string{})
if err != nil {
util.ErrFatalf("reading: %v", err)
}
Expand Down
20 changes: 12 additions & 8 deletions cmd/gator/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ var Cmd = &cobra.Command{
}

var (
flagFilenames []string
flagOutput string
flagIncludeTrace bool
flagGatherStats bool
flagImages []string
flagTempDir string
flagFilenames []string
flagOutput string
flagIncludeTrace bool
flagGatherStats bool
flagEnableExternalData bool
flagExternalDataProviders []string
flagImages []string
flagTempDir string
)

const (
Expand All @@ -72,20 +74,22 @@ func init() {
Cmd.Flags().StringVarP(&flagOutput, flagNameOutput, "o", "", fmt.Sprintf("Output format. One of: %s|%s.", stringJSON, stringYAML))
Cmd.Flags().BoolVarP(&flagIncludeTrace, "trace", "t", false, "include a trace for the underlying Constraint Framework evaluation.")
Cmd.Flags().BoolVarP(&flagGatherStats, "stats", "", false, "include performance stats returned from the Constraint Framework.")
Cmd.Flags().BoolVarP(&flagEnableExternalData, "external-data", "e", false, "enable external_data function in Constraint Templates.")
Cmd.Flags().StringArrayVarP(&flagExternalDataProviders, "external-data-providers", "", []string{}, "a file containing External Data Provider. Can be specified multiple times.")
Cmd.Flags().StringArrayVarP(&flagImages, flagNameImage, "i", []string{}, "a URL to an OCI image containing policies. Can be specified multiple times.")
Cmd.Flags().StringVarP(&flagTempDir, flagNameTempDir, "d", "", fmt.Sprintf("Specifies the temporary directory to download and unpack images to, if using the --%s flag. Optional.", flagNameImage))
}

func run(cmd *cobra.Command, args []string) {
unstrucs, err := reader.ReadSources(flagFilenames, flagImages, flagTempDir)
unstrucs, err := reader.ReadSources(flagFilenames, flagImages, flagTempDir, flagExternalDataProviders)
if err != nil {
cmdutils.ErrFatalf("reading: %v", err)
}
if len(unstrucs) == 0 {
cmdutils.ErrFatalf("no input data identified")
}

responses, err := test.Test(unstrucs, test.Opts{IncludeTrace: flagIncludeTrace, GatherStats: flagGatherStats})
responses, err := test.Test(unstrucs, test.Opts{IncludeTrace: flagIncludeTrace, GatherStats: flagGatherStats, EnableExternalData: flagEnableExternalData})
if err != nil {
cmdutils.ErrFatalf("auditing objects: %v", err)
}
Expand Down
9 changes: 8 additions & 1 deletion pkg/gator/reader/filereader.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

var allowedExtensions = []string{".yaml", ".yml", ".json"}

func ReadSources(filenames []string, images []string, tempDir string) ([]*unstructured.Unstructured, error) {
func ReadSources(filenames []string, images []string, tempDir string, externalDataProviderFiles []string) ([]*unstructured.Unstructured, error) {
var sources []*source

// Read from --filename flag
Expand All @@ -29,6 +29,13 @@ func ReadSources(filenames []string, images []string, tempDir string) ([]*unstru
}
sources = append(sources, s...)

// Read from --external-data-providers flag
s, err = readFiles(externalDataProviderFiles)
if err != nil {
return nil, fmt.Errorf("reading from filenames: %w", err)
}
sources = append(sources, s...)

// Read stdin
stdinUnstructs, err := readStdin()
if err != nil {
Expand Down
61 changes: 58 additions & 3 deletions pkg/gator/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ package test
import (
"context"
"fmt"

"github.com/open-policy-agent/frameworks/constraint/pkg/apis"
externaldataUnversioned "github.com/open-policy-agent/frameworks/constraint/pkg/apis/externaldata/unversioned"
templatesv1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1"
constraintclient "github.com/open-policy-agent/frameworks/constraint/pkg/client"
"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/rego"
frameworksexternaldata "github.com/open-policy-agent/frameworks/constraint/pkg/externaldata"
"github.com/open-policy-agent/gatekeeper/v3/pkg/expansion"
"github.com/open-policy-agent/gatekeeper/v3/pkg/gator/expand"
"github.com/open-policy-agent/gatekeeper/v3/pkg/gator/reader"
mutationtypes "github.com/open-policy-agent/gatekeeper/v3/pkg/mutation/types"
"github.com/open-policy-agent/gatekeeper/v3/pkg/target"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)
Expand All @@ -30,11 +32,55 @@ func init() {
// options for the Test func.
type Opts struct {
// Driver specific options
IncludeTrace bool
GatherStats bool
IncludeTrace bool
GatherStats bool
EnableExternalData bool
ExternalDataProviderCache *frameworksexternaldata.ProviderCache
}

func Test(objs []*unstructured.Unstructured, tOpts Opts) (*GatorResponses, error) {
// search for external data providers.
// this has to happen before creating the client, because rego.AddExternalDataProviderCache arg to the driver must have
// a ProviderCache already set up
var providerCache *frameworksexternaldata.ProviderCache
providerCache = frameworksexternaldata.NewCache()
for _, obj := range objs {
if !isExternalDataProvider(obj) {
continue
}

url, _, err := unstructured.NestedString(obj.Object, "spec", "url")
if err != nil {
return nil, err
}

timeout, _, err := unstructured.NestedFloat64(obj.Object, "spec", "timeout")
if err != nil {
return nil, err
}

caBundle, _, err := unstructured.NestedString(obj.Object, "spec", "caBundle")
if err != nil {
return nil, err
}

provider := externaldataUnversioned.Provider{
ObjectMeta: metav1.ObjectMeta{
Name: obj.GetName(),
},
Spec: externaldataUnversioned.ProviderSpec{
URL: url,
Timeout: int(timeout),
CABundle: caBundle,
},
}
err = providerCache.Upsert(&provider)
if err != nil {
return nil, err
}
}
tOpts.ExternalDataProviderCache = providerCache

// create the client
driver, err := makeRegoDriver(tOpts)
if err != nil {
Expand Down Expand Up @@ -174,6 +220,11 @@ func isConstraint(u *unstructured.Unstructured) bool {
return gvk.Group == "constraints.gatekeeper.sh"
}

func isExternalDataProvider(u *unstructured.Unstructured) bool {
gvk := u.GroupVersionKind()
return gvk.Group == "externaldata.gatekeeper.sh"
}

func makeRegoDriver(tOpts Opts) (*rego.Driver, error) {
var args []rego.Arg
if tOpts.GatherStats {
Expand All @@ -183,5 +234,9 @@ func makeRegoDriver(tOpts Opts) (*rego.Driver, error) {
args = append(args, rego.Tracing(tOpts.IncludeTrace))
}

if tOpts.EnableExternalData {
args = append(args, rego.AddExternalDataProviderCache(tOpts.ExternalDataProviderCache))
}

return rego.New(args...)
}

0 comments on commit 4fbc9be

Please sign in to comment.