borgeby / jarl

Jarl is an Open Policy Agent (OPA) evaluator for the JVM and Javascript, written in Clojure(Script)
Apache License 2.0
41 stars 5 forks source link

Java API eval arguments types and order are not working out of the box #160

Closed AdrianArnautu closed 1 year ago

AdrianArnautu commented 1 year ago

Hi all,

I'm playing around with jarl, the Java API and I've stumbled few the issues using the API. After some debugging I think found a way out and I want to confirm with you if this is an issue or it's my misunderstanding (I'm quite limited when it comes to Clojure)

TL;DR: the order of the arguments for eval method is wrong, and the type of data should be wrapped in a PersistentHashMap

Given the policy a bit simpler than in the example:

package policy

default allow := false

allow {
  input.user.roles == "admin"
}

With a plan opa build --target plan -e policy/allow . and then tar -zxvf bundle.tar.gz /plan.json We run a test:

   @Test
    void evaluationShouldReturnAllowTrue() throws IOException {
        var file = new File("plan.json");
        var jarl = Jarl.builder(file).build();
        var plan = jarl.getPlan("policy/allow");
        var input = Map.of(
                "user", Map.of(
                        "roles", "admin"
                )
        );
        Map<String, ?> data = Map.of();
        var resultSet = plan.eval(input, data);
        assertTrue(resultSet.allowed());
    }

and we get a failed result

expected: <true> but was: <false>
Expected :true
Actual   :false

The log: https://gist.github.com/AdrianArnautu/8ec8717dc72c52838e77af9f5b942cd8

in the logs I can observe DEBUG [jarl.eval:127] - DotStmt - '{}' at <{"type" "local", "value" 0}> is not a collection which indicates that it expects a different type, it expects an instance of clojure.lang.IPersistentCollection

If we adapt the test

   @Test
    void evaluationShouldReturnAllowTrue() throws IOException {
        var file = new File("plan.json");
        var jarl = Jarl.builder(file).build();
        var plan = jarl.getPlan("policy/allow");
        var input = (Map)PersistentHashMap.create(Map.of(
                "user", PersistentHashMap.create(Map.of(
                        "roles", "admin"
                ))
        ));
        Map<String, ?> data = Map.of();
        var resultSet = plan.eval(input, data);
        assertTrue(resultSet.allowed());
    }

I get the same result as before and the same line in the log - https://gist.github.com/AdrianArnautu/3525ff2d662a0416944df84286ffd450

But if we switch data with input it's all green ( https://gist.github.com/AdrianArnautu/b9f1f2f38e5c22761902dd96d9b42cb8 )

   @Test
    void evaluationShouldReturnAllowTrue() throws IOException {
        var file = new File("plan.json");
        var jarl = Jarl.builder(file).build();
        var plan = jarl.getPlan("policy/allow");
        var input = (Map)PersistentHashMap.create(Map.of(
                "user", PersistentHashMap.create(Map.of(
                        "roles", "admin"
                ))
        ));
        Map<String, ?> data = Map.of();
        var resultSet = plan.eval(data, input);
        assertTrue(resultSet.allowed());
    }

./opa version
Version: 0.47.0 Build Commit: 09019bea950a755d7bb3925d22917b3b62203f3a Build Timestamp: 2022-12-05T09:03:26Z Build Hostname: Mac-1670231591794.local Go Version: go1.19.3 Platform: darwin/arm64 WebAssembly: unavailable

Java 11 Clojure v1.11.1

johanfylling commented 1 year ago

Thank you @AdrianArnautu for your great analysis 🙂; we'll look into this. The Java API is still very immature, so please bear with us.

johanfylling commented 1 year ago

This has been fixed by #163. Thank you for your input @AdrianArnautu!