diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 4b740963f..2af37886f 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -92,6 +92,11 @@ jobs: e2e-envoy-grpc: name: Envoy gRPC End-to-End Test runs-on: ubuntu-18.04 + strategy: + matrix: + include: + - eval: wasm + - eval: rego steps: - name: Check out code uses: actions/checkout@v2 @@ -104,7 +109,7 @@ jobs: working-directory: examples/grpc - name: Run test - run: make test-setup test + run: make test-setup test EVAL_TARGET=${{ matrix.eval }} working-directory: examples/grpc - name: Run test log dump and cleanup diff --git a/envoyauth/evaluation.go b/envoyauth/evaluation.go index 4206c4ff7..e5551dfa3 100644 --- a/envoyauth/evaluation.go +++ b/envoyauth/evaluation.go @@ -27,7 +27,12 @@ type EvalContext interface { SetPreparedQuery(*rego.PreparedEvalQuery) } -//Eval - Evaluates an input against a provided EvalContext and yields result +// EvalContextWithTarget is the interface that allows setting the evaluation's target engine. +type EvalContextWithTarget interface { + Target() string +} + +// Eval evaluates an input against a provided EvalContext and yields result func Eval(ctx context.Context, evalContext EvalContext, input ast.Value, result *EvalResult, opts ...func(*rego.Rego)) error { var err error @@ -87,13 +92,18 @@ func constructPreparedQuery(evalContext EvalContext, txn storage.Transaction, m var pq rego.PreparedEvalQuery evalContext.PreparedQueryDoOnce().Do(func() { + target := "rego" + if ec, ok := evalContext.(EvalContextWithTarget); ok { + target = ec.Target() + } opts = append(opts, rego.Metrics(m), rego.ParsedQuery(evalContext.ParsedQuery()), rego.Compiler(evalContext.Compiler()), rego.Store(evalContext.Store()), rego.Transaction(txn), - rego.Runtime(evalContext.Runtime())) + rego.Runtime(evalContext.Runtime()), + rego.Target(target)) r := rego.New(opts...) diff --git a/examples/grpc/Makefile b/examples/grpc/Makefile index 70672c610..112f2aae7 100644 --- a/examples/grpc/Makefile +++ b/examples/grpc/Makefile @@ -2,6 +2,7 @@ SHELL:=bash GRPCURL_IMAGE:=fullstorydev/grpcurl:v1.7.0 GRPCURL=docker run --network=host -i --rm -v $$(pwd)/testsrv.pb:/testsrv.pb $(GRPCURL_IMAGE) \ -d @ -plaintext -protoset /testsrv.pb 127.0.0.1:51051 +EVAL_TARGET?=rego all: testsrv.pb testsrv-image test-setup test test-teardown @@ -14,7 +15,7 @@ testsrv.pb: testsrv/test.proto .PHONY: test-setup test-setup: - docker-compose up -d + EVAL_TARGET=$(EVAL_TARGET) docker-compose up -d .PHONY: test-teardown test-teardown: diff --git a/examples/grpc/docker-compose.yaml b/examples/grpc/docker-compose.yaml index 47e918675..1ce679cb2 100644 --- a/examples/grpc/docker-compose.yaml +++ b/examples/grpc/docker-compose.yaml @@ -14,12 +14,13 @@ services: command: - run - --server - - --config-file=/opa.yaml + - --config-file=/opa-${EVAL_TARGET}.yaml - /policy.rego volumes: - ./testsrv.pb:/testsrv.pb - ./policy.rego:/policy.rego - - ./opa.yaml:/opa.yaml + - ./opa-wasm.yaml:/opa-wasm.yaml + - ./opa-rego.yaml:/opa-rego.yaml testsrv: image: testsrv:latest ports: diff --git a/examples/grpc/opa.yaml b/examples/grpc/opa-rego.yaml similarity index 100% rename from examples/grpc/opa.yaml rename to examples/grpc/opa-rego.yaml diff --git a/examples/grpc/opa-wasm.yaml b/examples/grpc/opa-wasm.yaml new file mode 100644 index 000000000..2439d13fa --- /dev/null +++ b/examples/grpc/opa-wasm.yaml @@ -0,0 +1,10 @@ +plugins: + envoy_ext_authz_grpc: + addr: ":9191" + path: envoy/authz/allow + dry-run: false + enable-reflection: true + proto-descriptor: /testsrv.pb + eval-target: wasm +decision_logs: + console: true diff --git a/internal/internal.go b/internal/internal.go index 0a2b34d39..16f643e28 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -41,10 +41,13 @@ import ( "github.com/open-policy-agent/opa/util" ) -const defaultAddr = ":9191" -const defaultPath = "envoy/authz/allow" -const defaultDryRun = false -const defaultEnableReflection = false +const ( + defaultAddr = ":9191" + defaultPath = "envoy/authz/allow" + defaultDryRun = false + defaultEnableReflection = false + defaultEvalTarget = "rego" +) // PluginName is the name to register with the OPA plugin manager const PluginName = "envoy_ext_authz_grpc" @@ -58,6 +61,7 @@ func Validate(m *plugins.Manager, bs []byte) (*Config, error) { Addr: defaultAddr, DryRun: defaultDryRun, EnableReflection: defaultEnableReflection, + EvalTarget: defaultEvalTarget, } if err := util.Unmarshal(bs, &cfg); err != nil { @@ -133,6 +137,7 @@ type Config struct { Path string `json:"path"` DryRun bool `json:"dry-run"` EnableReflection bool `json:"enable-reflection"` + EvalTarget string `json:"eval-target"` parsedQuery ast.Body ProtoDescriptor string `json:"proto-descriptor"` protoSet *protoregistry.Files @@ -147,6 +152,8 @@ type envoyExtAuthzGrpcServer struct { interQueryBuiltinCache iCache.InterQueryCache } +var _ envoyauth.EvalContextWithTarget = (*envoyExtAuthzGrpcServer)(nil) + type envoyExtAuthzV2Wrapper struct { v3 *envoyExtAuthzGrpcServer } @@ -167,6 +174,10 @@ func (p *envoyExtAuthzGrpcServer) Runtime() *ast.Term { return p.manager.Info } +func (p *envoyExtAuthzGrpcServer) Target() string { + return p.cfg.EvalTarget +} + func (p *envoyExtAuthzGrpcServer) PreparedQueryDoOnce() *sync.Once { return p.preparedQueryDoOnce } @@ -243,6 +254,7 @@ func (p *envoyExtAuthzGrpcServer) listen() { "path": p.cfg.Path, "dry-run": p.cfg.DryRun, "enable-reflection": p.cfg.EnableReflection, + "eval-target": p.cfg.EvalTarget, }).Info("Starting gRPC server.") p.manager.UpdatePluginStatus(PluginName, &plugins.Status{State: plugins.StateOK})