Skip to content

Commit

Permalink
Open-policy-agent: Insert config labels in opa runtime (#2801)
Browse files Browse the repository at this point in the history
  • Loading branch information
wisinghe authored Jan 4, 2024
1 parent 07dee9e commit fd2817c
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ func TestAuthorizeRequestFilter(t *testing.T) {
backendHeaders: make(http.Header),
removeHeaders: make(http.Header),
},
{
msg: "Allow Matching Environment",
bundleName: "somebundle.tar.gz",
regoQuery: "envoy/authz/allow_runtime_environment",
requestPath: "/allow",
expectedStatus: http.StatusOK,
expectedBody: "Welcome!",
expectedHeaders: make(http.Header),
backendHeaders: make(http.Header),
removeHeaders: make(http.Header),
},
{
msg: "Simple Forbidden",
bundleName: "somebundle.tar.gz",
Expand Down Expand Up @@ -159,6 +170,10 @@ func TestAuthorizeRequestFilter(t *testing.T) {
allow_context_extensions {
input.attributes.contextExtensions["com.mycompany.myprop"] == "myvalue"
}
allow_runtime_environment {
opa.runtime().config.labels.environment == "test"
}
default allow_object = {
"allowed": false,
Expand Down Expand Up @@ -213,6 +228,9 @@ func TestAuthorizeRequestFilter(t *testing.T) {
"resource": "/bundles/{{ .bundlename }}"
}
},
"labels": {
"environment": "test"
},
"plugins": {
"envoy_ext_authz_grpc": {
"path": %q,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,24 @@ func TestAuthorizeRequestFilter(t *testing.T) {
expectedBody: "Welcome from policy!",
expectedHeaders: map[string][]string{"X-Ext-Auth-Allow": {"yes"}},
},
{
msg: "Allow With opa.runtime execution",
bundleName: "somebundle.tar.gz",
regoQuery: "envoy/authz/allow_object",
requestPath: "allow/production",
expectedStatus: http.StatusOK,
expectedBody: "Welcome to production evaluation!",
expectedHeaders: map[string][]string{"X-Ext-Auth-Allow": {"yes"}},
},
{
msg: "Deny With opa.runtime execution",
bundleName: "somebundle.tar.gz",
regoQuery: "envoy/authz/allow_object",
requestPath: "allow/test",
expectedStatus: http.StatusForbidden,
expectedBody: "Unauthorized Request",
expectedHeaders: map[string][]string{"X-Ext-Auth-Allow": {"no"}},
},
{
msg: "Allow With Structured Body",
bundleName: "somebundle.tar.gz",
Expand Down Expand Up @@ -105,7 +123,7 @@ func TestAuthorizeRequestFilter(t *testing.T) {
"allowed": false,
"headers": {"x-ext-auth-allow": "no"},
"body": "Unauthorized Request",
"http_status": 401
"http_status": 403
}
allow_object = response {
Expand All @@ -117,6 +135,28 @@ func TestAuthorizeRequestFilter(t *testing.T) {
"http_status": 200
}
}
allow_object = response {
input.parsed_path = [ "allow", "production" ]
opa.runtime().config.labels.environment == "production"
response := {
"allowed": true,
"headers": {"x-ext-auth-allow": "yes"},
"body": "Welcome to production evaluation!",
"http_status": 200
}
}
allow_object = response {
input.parsed_path = [ "allow", "test" ]
opa.runtime().config.labels.environment == "test"
response := {
"allowed": true,
"headers": {"x-ext-auth-allow": "yes"},
"body": "Welcome to test evaluation!",
"http_status": 200
}
}
allow_object_structured_body = response {
input.parsed_path = [ "allow", "structured" ]
Expand Down Expand Up @@ -151,6 +191,9 @@ func TestAuthorizeRequestFilter(t *testing.T) {
"url": %q
}
},
"labels": {
"environment" : "production"
},
"bundles": {
"test": {
"resource": "/bundles/{{ .bundlename }}"
Expand Down
17 changes: 16 additions & 1 deletion filters/openpolicyagent/openpolicyagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ func New(store storage.Store, configBytes []byte, instanceConfig OpenPolicyAgent

var logger logging.Logger = &QuietLogger{target: logging.Get()}
logger = logger.WithFields(map[string]interface{}{"skipper-filter": filterName})
manager, err := plugins.New(configBytes, id, store, plugins.Logger(logger))
manager, err := plugins.New(configBytes, id, store, configLabelsInfo(*opaConfig), plugins.Logger(logger))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -449,6 +449,21 @@ func waitFunc(ctx context.Context, fun func() bool, interval time.Duration) erro
}
}

func configLabelsInfo(opaConfig config.Config) func(*plugins.Manager) {
info := ast.NewObject()
labels := ast.NewObject()
labelsWrapper := ast.NewObject()

for key, value := range opaConfig.Labels {
labels.Insert(ast.StringTerm(key), ast.StringTerm(value))
}

labelsWrapper.Insert(ast.StringTerm("labels"), ast.NewTerm(labels))
info.Insert(ast.StringTerm("config"), ast.NewTerm(labelsWrapper))

return plugins.Info(ast.NewTerm(info))
}

func (opa *OpenPolicyAgentInstance) InstanceConfig() *OpenPolicyAgentInstanceConfig {
return &opa.instanceConfig
}
Expand Down
40 changes: 40 additions & 0 deletions filters/openpolicyagent/openpolicyagent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/storage/inmem"
"io"
"net/http"
Expand All @@ -16,6 +17,7 @@ import (
authv3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
_struct "github.com/golang/protobuf/ptypes/struct"
"github.com/open-policy-agent/opa-envoy-plugin/envoyauth"
opaconf "github.com/open-policy-agent/opa/config"
opasdktest "github.com/open-policy-agent/opa/sdk/test"
"github.com/opentracing/opentracing-go"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -122,6 +124,9 @@ func mockControlPlaneWithDiscoveryBundle(discoveryBundle string) (*opasdktest.Se
"url": %q
}
},
"labels": {
"environment": "envValue"
},
"discovery": {
"name": "discovery",
"resource": %q,
Expand Down Expand Up @@ -256,6 +261,41 @@ func TestOpaActivationSuccessWithDiscovery(t *testing.T) {
assert.Equal(t, 1, len(registry.instances))
}

func TestOpaLabelsSetInRuntimeWithDiscovery(t *testing.T) {
_, config := mockControlPlaneWithDiscoveryBundle("bundles/discovery")

registry := NewOpenPolicyAgentRegistry(WithReuseDuration(1*time.Second), WithCleanInterval(1*time.Second))

cfg, err := NewOpenPolicyAgentConfig(WithConfigTemplate(config))
assert.NoError(t, err)

instance, err := registry.NewOpenPolicyAgentInstance("test", *cfg, "testfilter")
assert.NoError(t, err)
assert.NotNil(t, instance)
assert.NotNil(t, instance.Runtime())

value := instance.Runtime().Value

j, err := ast.JSON(value)
assert.NoError(t, err)

if m, ok := j.(map[string]interface{}); ok {
configObject := m["config"]
assert.NotNil(t, configObject)

jsonData, err := json.Marshal(configObject)
assert.NoError(t, err)

var parsed *opaconf.Config
json.Unmarshal(jsonData, &parsed)

labels := parsed.Labels
assert.Equal(t, labels["environment"], "envValue")
} else {
t.Fatalf("Failed to process runtime value %v", j)
}
}

func TestOpaActivationFailureWithWrongServiceConfig(t *testing.T) {
configWithUnknownService := []byte(`{
"discovery": {
Expand Down

0 comments on commit fd2817c

Please sign in to comment.