Expanding the Rego syntax to support not-bodies (not blocks?): `not {...}`
For a not block to successfully evaluate, its body must not successfully evaluate. If evaluation causes iteration, all evaluation paths must fail.
Fixes: #8402
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
Timeouts passed via context are not honored because builtins that
parse exponents dont include context and will run with unrestricted
size on the exponents. Added an exponent limit checker based
on rough benchmakrking data of whats a reasonabile limit.
Fixes: #8326
Signed-off-by: Isaiah Vita <vita.isaiah@gmail.com>
* topdown: add failing tests for graph.reachable_paths with shared ancestors
Adds a regression test (shared_ancestor) reproducing the bug reported in
#5871: given a graph where node 4 has edges to both 3 and 2, and 3 also
has an edge to 2, graph.reachable_paths from 5 drops the path [5,4,2,1].
Also corrects the expected result for the existing cycle_1022_3 test, which
was asserting the buggy output ([one,five,six] truncated) rather than the
correct complete path [one,five,six,seven,eight,three].
Signed-off-by: David Marne <david.marne@workiva.com>
* topdown: fix graph.reachable_paths dropping paths with shared ancestors
graph.reachable_paths had two bugs that caused paths to be silently dropped
when a node is reachable via multiple routes (diamond-shaped graphs).
Bug 1: the `reached` set was mutated and shared across sibling recursive
calls. After branch A finished traversal and added nodes to `reached`,
branch B would see those nodes as already visited and terminate early,
emitting a truncated path instead of continuing.
Fix: copy `reached` once per pathBuilder invocation and pass the copy to
all recursive calls. Each branch now has its own ancestor-only visited set.
Bug 2: ast.NewArray stores the slice it receives directly (elems: a)
without copying. When sibling calls appended to a shared backing array,
the in-place write by one sibling corrupted the already-committed path
term of a previous sibling.
Fix: pass append([]*ast.Term(nil), path...) to each recursive call,
giving each branch its own independent backing array.
Signed-off-by: David Marne <david.marne@workiva.com>
---------
Signed-off-by: David Marne <david.marne@workiva.com>
* distributedtracing: export Prometheus metrics via OTLP
Add support for pushing OPA's existing Prometheus metrics to an
OpenTelemetry collector via OTLP, eliminating the need for a dedicated
scraper sidecar. Uses the OTel Prometheus bridge to read from OPA's
prometheus.Registry and export through an OTLP metric exporter (gRPC
or HTTP), reusing the same address and TLS configuration as traces.
New config fields: distributed_tracing.metrics (bool, default false)
and distributed_tracing.metrics_export_interval_ms (int, default 60000).
Fixes#7591
Signed-off-by: Michael Munch <mm.munk@gmail.com>
* metricsexport: decouple metrics export into top-level config section
Extract metrics export from distributed_tracing into its own
metrics_export config section with independent type (otlp/grpc,
otlp/http), address, and TLS settings. This allows exporting
Prometheus metrics via OTLP without enabling tracing, and to a
different endpoint than traces.
- Extract shared TLS helpers into internal/tlsutil
- Add MetricsExport field to top-level Config
- Create internal/metricsexport package with Init, config parsing
- Remove metrics fields from distributedtracing
- Update runtime to call metricsexport.Init separately
- Move e2e tests to v1/test/e2e/metricsexport
- Add Metrics Export section to configuration docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Michael Munch <mm.munk@gmail.com>
* ci: retrigger checks
Signed-off-by: Michael Munch <mm.munk@gmail.com>
* go.mod: upgrade dependencies downgraded during rebase
Modules like containerd, go-sqlbuilder, OpenTelemetry, and golang.org/x/*
were at older versions than main after a rebase. Upgrade them to match or
exceed main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Michael Munch <mm.munk@gmail.com>
* Update internal/distributedtracing/distributedtracing_test.go
Signed-off-by: Michael Munch <mm.munk@gmail.com>
---------
Signed-off-by: Michael Munch <mm.munk@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Disabled by default. To enable, `not` future keyword must be present in capabilities and imported into Rego module.
Implements: #8391
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
When `--h2c` is passed, HTTP2 will also be used on the unix domain socket.
Previously, it had no effect on UDS, only on TCP connections.
Fixes#8282.
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
Originally meant to be `array.concat_n`, but this name is better
as the behavior of this function differs from `array.concat` —
namely that `array.flatten` accepts any type of valued in the
input array. Only arrays are however flattened, and the rest
are appended directly to the flattened output.
Note that this function only flattens at the topmost level of
the input array — not recursively! A cursory look
at a few other languages suggest a single level is the common case.
But if others feel we should flstten more, I'm happy to make an update.
The C code for a Wasm implementstion here is cowboy coded, and
I did not manage to run the tests on my machine due to some
`docker` <-> `container` differences. I mostly just imitated
the existing code in the array category. I doubt it'll work
on the first try, but only CI can judge me.
Also:
- Remove `opa fmt` step from the Rego CI step, as this is done by
Regal anyway a little later in the list of tasks.
- Replace some hard-coded `docker` names in the `Makefile` with `$(DOCKER)`
- Added name of built-in function missing to the unsupportedBuiltinErr
error, as it has happened a few times now that I've used `:=` in a
query, and had no clue what built-in it referred to.
Fixes#8226
Signed-off-by: Anders Eknert <anders.eknert@apple.com>
Current implementation of render_template passes in an explicit
missingkey=error option when rendering a Golang template. That's
not the default behavior for Golang, so it's an unexpected result.
Fixes#7931.
Signed-off-by: Colin Lacy <colinjlacy@gmail.com>
Fix canGenerateCheapRangeStep to check operands[2] (step) instead of
operands[1] (y) when determining whether to use the fast path for
numbers.range_step.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Relevant: #8151.
New tests: add some cases for these builtins:
* regex.match
* regex.replace
* strings.count
* regex.find_n
* regex.split
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
Adding string interpolation support to the Rego language.
An interpolated string is composed of a template-string that can contain zero or more template-expressions that interpolates values into the string generated at eval-time.
Requires the `template_strings` capability feature and `internal.template_string` built-in function.
Implements: #4733
Parsing is generally fast, so this mainly improves performance
of creating big bundles with many Rego files in them. For Regal's
embedded bundle, loading it from memory would previously take 16
ms on my laptop, and now it takes 9 ms. There are other things
in this process that could be concurrent too, like JSON unmarshalling
of multiple data files. But starting with parsing modules.
This PR adds `errgroup` as a direct dependency (previously indirect)
as it is a nicer way to work with wait groups, and one that can be
useful elsewhere in the codebase (like in the compiler).
Also, and as usual, went off on a bit of a tangent refactoring code
related to the bundle build process, and made sure to use some common
helpers in code where available.
Signed-off-by: Anders Eknert <anders.eknert@apple.com>
- Bump golangci-lint -> 2.6.2
- Fix all `deprecatedComment` "notices should be in a dedicated paragraph, separated from the rest" reports
- Enable `appendCombine` and fix all "appendCombine: can combine chain of X appends into one" notices
- Enable `preferFprint` and fix the few reported issues
- Fix various issues reported only once or twice, like `zeroByteRepeat`
Signed-off-by: Anders Eknert <anders.eknert@apple.com>
Using `rand.intn` test cases as template, we create similar tests
that verify consistent values returned by `uuid.rfc4122` and `time.now_ns`
builtins when invoked during the same evaluation/query.
These tests can also aid compliance regression testing for other OPA implementations,
such as Swift.
Signed-off-by: Dmitry Frenkel <d_frenkel@apple.com>
Before, we'd see these benchmarks die with
benchmark.go:412: B.Loop called with timer stopped
Now, we can run them again:
```
% go test -bench=. -v -run=XXX ./v1/test/e2e/authz
{
"level": "info",
"msg": "Test server ready and listening on: http://127.0.0.1:64200",
"time": "2025-10-15T11:44:06+02:00"
}
goos: darwin
goarch: arm64
pkg: github.com/open-policy-agent/opa/v1/test/e2e/authz
cpu: Apple M4 Max
BenchmarkRESTAuthzForbidAuthn
BenchmarkRESTAuthzForbidAuthn-16 22623 52375 ns/op
BenchmarkRESTAuthzForbidPath
BenchmarkRESTAuthzForbidPath-16 16729 71916 ns/op
BenchmarkRESTAuthzForbidMethod
BenchmarkRESTAuthzForbidMethod-16 16434 72963 ns/op
BenchmarkRESTAuthzAllow10Paths
BenchmarkRESTAuthzAllow10Paths-16 15883 74936 ns/op
BenchmarkRESTAuthzAllow100Paths
BenchmarkRESTAuthzAllow100Paths-16 10000 109283 ns/op
BenchmarkRESTAuthzAllow1000Paths
BenchmarkRESTAuthzAllow1000Paths-16 2731 462167 ns/op
PASS
ok github.com/open-policy-agent/opa/v1/test/e2e/authz 13.349s
```
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
Have done this some time in the past, but there was a few
new issues this would highlight now that we're on Go 1.24.
Mostly:
- Use `b.Loop()` in benchmarks
- Use `strings.SplitSeq` where possible
- Remove `omitempty` tag for types that can't be empty
Signed-off-by: Anders Eknert <anders@eknert.com>
The assertions are stricter now, e.g. we're also checking that nothing
is emitted to stderr.
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
Running `make test` on a new Macbook Pro could previously
fail with errors like "connect: can't assign requested address".
This can be alleviated by increasing the range of ports to open,
but setting a limit for idle connections in the tests seems like
the better solution.
Signed-off-by: Anders Eknert <anders@eknert.com>
Go 1.23 is no longer supported as per Go release policy.
Changes:
- Use Go v1.24.6 as the project SDK requirement
- Apply lint fixes for Go 1.24
- Fix "non-constant format string in call" issues as seen in CI.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Introducing the `io.jwt.verify_eddsa` built-in, and adding support to the following built-ins:
* `io.jwt.decode_verify`
* `io.jwt.encode_sign`
* `io.jwt.encode_sign_raw`
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
* plugin/bundle: Correct bundle delay behavior
I ran into an issue when testing an earlier change:
https://github.com/open-policy-agent/opa/actions/runs/16646981900/job/47110035165
I found that this test generated around 100,000 lines of errors showing
the bundle downloader running.
This can be be tested using:
```
go test -v ./v1/plugins/bundle -count=1 2>&1 | grep -c "request failed"
```
This commit closes managers and plugins correctly.
Signed-off-by: Charlie Egan <charlie@styra.com>
* download: Update stop to be idempotent
I had some race detector issues with TestStartStopWithLongPollNotSupported
https://github.com/open-policy-agent/opa/actions/runs/16722869930/job/47334690407?pr=7812
I think this is a deadlock around multiple calls to Stop dead locking
updating the stopped var.
Signed-off-by: Charlie Egan <charlie@styra.com>
---------
Signed-off-by: Charlie Egan <charlie@styra.com>
A number of benchmarks did not have a `for range b.N` (or equivalent) loop in
them, leading to nothing being measured. This PR fixes that, along with some
cleanups in benchmarks found along the way.
Also remove `b.StopTimer` where not absolutely necessary, as that is
[notoriously buggy](https://github.com/golang/go/issues/27217), and had some
benchmarks hang for a very long time.
Signed-off-by: Anders Eknert <anders@styra.com>
I'm still not sure where this mutation occurs, as the append operation
done in `walk` returns a copy and shouldn't mutate. But at least creating
a shallow copy rather than a slice fixes the issue, and is still quite
performant compared to the previous implementation that did a deep-copy
of the path in each iteration.
Fixes#7656
Signed-off-by: Anders Eknert <anders@styra.com>
While most uses of `walk` in Regal are able to leverage the optimized
"no path" version of the built-in, there are still many places where
we need both the path and the value. Optimizing this has been really
tricky (see comments in code), but last night I had an idea which proved
to have an incredible impact for the path-value form of `walk` (which
outside of Regal is the common one).
Instead of making a deep-copy of the path array in each iteration,
we now make a shallow copy. `.Copy`ing every item in the path was a
massive allocation source, and I don't think I've seen a single change
in OPA have this big impact before. **5 million allocations down**, or
almost 10% of all allocations performed in `regal lint bundle`.
**`regal lint bundle`, OPA main vs change**
```
966876500 ns/op 2960650884 B/op 56181759 allocs/op
934882916 ns/op 2807204756 B/op 51339375 allocs/op
```
Signed-off-by: Anders Eknert <anders@styra.com>
Following up on #7566, and now applying the more exciting
modernizations. fmt.Appendf was new to me! But especially
the contains checks are so much better IMHO. I have reviewed
all changes myself and did a few manual changes where it
became obvious that things could be improved a little further.
(the modernize analyzer still has some issues running against
OPA, and I have manually worked around those for the time being)
Signed-off-by: Anders Eknert <anders@styra.com>
This change still follows the approach thought up in #6996, but now does
it more consistently: the extra args accumulated through (multiple)
with-replacements using variables are now put into the funcstackj, and
consistently affect the planning of functions in "higher" gens.
Fixes#5311.
Signed-off-by: Stephan Renatus <stephan@styra.com>
This updates gqlparser from version ~v2.5.1 and the June 2018 GraphQL spec to
v2.5.26 and the October 2021 GraphQL spec.
Signed-off-by: Rob Myers <1243316+robmyersrobmyers@users.noreply.github.com>
When planning rules like these:
```
package authz
p.allow[action][resource] if { action := "list"; resource := "fruit" }
p.unrelated.eat.veggies if true
resp := p[input.rule][input.action][input.resource]
```
we ended up with a broken CallDynamic statement. Since the first ref
rule is planned as `g0.data.authz.p.allow` and builds an object return
value, and the second rule is planned as
`g0.data.authz.p.unrelated.eat.veggies` with a boolean return value, we cannot
dynamically dispatch their calls.
With this change, the previously existing "unbalanced ruletrie" check now
also hits before reaching the end of the ref. It'll catch this situation
and avoid optimizing the dispatch. We'll end up with a longer, less
efficient, but correct plan.
Signed-off-by: Stephan Renatus <stephan@styra.com>
The previous check there was running into false positives, as the added
test case showed. We should only count relevant ruletrie child nodes.
Signed-off-by: Stephan Renatus <stephan@styra.com>
`TestControlPlaneSpans` could case a race condition, where the discovery plugin is manually triggered before/during server initialization, resulting in the manager config being changed while actively consumed.
Replacing `Runtime.serverInitialized` boolean field with more granular enum type state, to allow test-runtime to hold off on triggering plugins until runtime is actively waiting for plugin ready state.
Currently, manager config writes are guarded by an internal mutex, while config reads are largely unguarded. A broader fix here might be to deprecate the public `plugins.Manager.Context` field, replacing it with a getter that guards the config with an r/w-lock.
Also fixing:
* Possible race condition in telemetry reporter by using r/w-mutex guarded compiler getter instead of direct field access
* AWS signing tests where signing randomly failed because of too small mock random value used in test
Signed-off-by: Johan Fylling <johan.dev@fylling.se>