Add rego_version attribute to bundle manifest (#6579)

Adding a global `rego_version` attribute to bundle manifest, to inform OPA runtime about what rego-version (v0/v1) to use to parse/compile contained Rego files.
The rego-version of individual Rego files can be overridden through the `file_rego_versions` manifest attribute.

Implements: #6578

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
This commit is contained in:
Johan Fylling
2024-04-10 19:06:07 +02:00
committed by GitHub
parent ae636de8c0
commit e23d771711
23 changed files with 6130 additions and 53 deletions
+129
View File
@@ -589,6 +589,135 @@ func TestOneShotV1Compatible(t *testing.T) {
}
}
func TestOneShotWithBundleRegoVersion(t *testing.T) {
tests := []struct {
note string
bundleRegoVersion int
module string
expErrs []string
}{
{
note: "v0.x bundle, keywords not used",
bundleRegoVersion: 0,
module: `package test
p[1] {
input.x == 2
}`,
},
{
note: "v0.x bundle, keywords used but not imported",
bundleRegoVersion: 0,
module: `package test
p contains 1 if {
input.x == 2
}`,
expErrs: []string{
"rego_parse_error: var cannot be used for rule name",
"rego_parse_error: number cannot be used for rule name",
},
},
{
note: "v0.x bundle, keywords used, rego.v1 imported",
bundleRegoVersion: 0,
module: `package test
import rego.v1
p contains 1 if {
input.x == 2
}`,
},
{
note: "v1.0 bundle, keywords not used",
bundleRegoVersion: 1,
module: `package test
p[1] {
input.x == 2
}`,
expErrs: []string{
"rego_parse_error: `if` keyword is required before rule body",
"rego_parse_error: `contains` keyword is required for partial set rules",
},
},
{
note: "v1.0 bundle, keywords used, not imported",
bundleRegoVersion: 1,
module: `package test
p contains 1 if {
input.x == 2
}`,
},
{
note: "v1.0, keywords used, rego.v1 imported",
bundleRegoVersion: 1,
module: `package test
import rego.v1
p contains 1 if {
input.x == 2
}`,
},
}
for _, tc := range tests {
t.Run(tc.note, func(t *testing.T) {
ctx := context.Background()
fixture := newTestFixture(t)
fixture.d = New(Config{}, fixture.client, "bundles/custom").
WithCallback(fixture.oneShot)
fixture.server.expEtag = "some etag value"
fixture.server.bundles["custom"] = bundle.Bundle{
Manifest: bundle.Manifest{RegoVersion: &tc.bundleRegoVersion},
Data: map[string]interface{}{},
Modules: []bundle.ModuleFile{
{
Path: "test.rego",
Raw: []byte(tc.module),
},
},
}
defer fixture.server.stop()
// check etag on the downloader is empty
if fixture.d.etag != "" {
t.Fatalf("Expected empty downloader ETag but got %v", fixture.d.etag)
}
// simulate successful bundle activation and check updated etag on the downloader
fixture.server.expCode = 0
err := fixture.d.oneShot(ctx)
if tc.expErrs != nil {
if err == nil {
t.Fatal("Expected error but got nil")
}
for _, expErr := range tc.expErrs {
if !strings.Contains(err.Error(), expErr) {
t.Fatalf("Expected error to contain:\n\n%v\n\nbut got\n\n%v", expErr, err)
}
}
} else {
if err != nil {
t.Fatal("Unexpected:", err)
}
if fixture.d.etag != fixture.server.expEtag {
t.Fatalf("Expected downloader ETag %v but got %v", fixture.server.expEtag, fixture.d.etag)
}
if fixture.updates[0].Bundle == nil {
// 200 response on first request, bundle should be present
t.Errorf("Expected bundle in response")
}
if fixture.updates[0].Bundle.Etag != fixture.server.expEtag {
t.Fatalf("Expected bundle ETag %v but got %v", fixture.server.expEtag, fixture.updates[0].Bundle.Etag)
}
}
})
}
}
func TestFailureAuthn(t *testing.T) {
ctx := context.Background()
+5 -4
View File
@@ -7,13 +7,14 @@ import (
"context"
"encoding/base64"
"fmt"
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/bundle"
"net/http"
"strings"
"testing"
"time"
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/bundle"
"github.com/open-policy-agent/opa/keys"
"github.com/open-policy-agent/opa/plugins/rest"
)
@@ -67,9 +68,9 @@ func TestOCIDownloaderWithRegoV1Bundle(t *testing.T) {
regoVersion ast.RegoVersion
expErr string
}{
// The bundle contains a v1 rego_version attr, so we expect no errors regardless of parser regoVersion.
{
note: "non-1.0 compatible OCI downloader",
expErr: "rego_parse_error",
note: "non-1.0 compatible OCI downloader",
},
{
note: "1.0 compatible OCI downloader",
+2 -2
View File
@@ -8,8 +8,8 @@
"layers":[
{
"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip",
"digest":"sha256:cc09b0f5ac97b11637c96ff1b0fbbc287c5ba0169813edaa71fe58424e95f0b7",
"size":695,
"digest":"sha256:0f93a2c5964d7c8b676e3b507b6bc3b771c086428dece6f84256b9948cb3f256",
"size":830,
"annotations":{
"org.opencontainers.image.created":"2022-02-11T09:00:07Z",
"org.opencontainers.image.title":"dani/testpol"
Binary file not shown.
+2 -2
View File
@@ -8,8 +8,8 @@
"layers":[
{
"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip",
"digest":"sha256:e060c7b9558fad3ec85df5ffa19d0d019f839c36d7ec146977c871dcbc70885e",
"size":629,
"digest":"sha256:7fccf82798e6e627afd04144889570d966583788473db2888f0d0d325904d273",
"size":764,
"annotations":{
"org.opencontainers.image.created":"2022-02-11T09:00:07Z",
"org.opencontainers.image.title":"dani/testpol"
BIN
View File
Binary file not shown.