Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 22 additions & 23 deletions core/src/main/java/com/styra/opa/wasm/OpaPolicy.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.styra.opa.wasm;

import com.dylibso.chicory.runtime.ByteBufferMemory;
import com.dylibso.chicory.runtime.ByteArrayMemory;
import com.dylibso.chicory.runtime.Memory;
import com.dylibso.chicory.wasm.types.MemoryLimits;
import com.fasterxml.jackson.core.JsonProcessingException;
Expand Down Expand Up @@ -35,19 +35,19 @@ public class OpaPolicy {
private OpaPolicy(OpaWasm wasm) {
this.wasm = wasm;

if (!(wasm.opaWasmAbiVersion().getValue() == 1L
&& wasm.opaWasmAbiMinorVersion().getValue() == 3L)) {
if (!(wasm.exports().opaWasmAbiVersion().getValue() == 1L
&& wasm.exports().opaWasmAbiMinorVersion().getValue() == 3L)) {
throw new IllegalArgumentException(
"Invalid version, supported 1.3, detected "
+ wasm.opaWasmAbiVersion()
+ wasm.exports().opaWasmAbiVersion()
+ "."
+ wasm.opaWasmAbiMinorVersion());
+ wasm.exports().opaWasmAbiMinorVersion());
}

this.baseHeapPtr = wasm.opaHeapPtrGet();
this.baseHeapPtr = wasm.exports().opaHeapPtrGet();
this.dataHeapPtr = this.baseHeapPtr;
this.dataAddr = -1;
wasm.opaHeapPtrSet(this.dataHeapPtr);
wasm.exports().opaHeapPtrSet(this.dataHeapPtr);
}

public OpaPolicy entrypoint(int entrypoint) {
Expand All @@ -61,26 +61,26 @@ public OpaPolicy entrypoint(String entrypoint) {
}

private int loadJson(String data) {
var dataStrAddr = wasm.opaMalloc(data.length());
var dataStrAddr = wasm.exports().opaMalloc(data.length());
wasm.memory().writeCString(dataStrAddr, data);
var dstAddr = wasm.opaJsonParse(dataStrAddr, data.length());
wasm.opaFree(dataStrAddr);
var dstAddr = wasm.exports().opaJsonParse(dataStrAddr, data.length());
wasm.exports().opaFree(dataStrAddr);
return dstAddr;
}

private String dumpJson(int addr) {
int resultStrAddr = wasm.opaJsonDump(addr);
int resultStrAddr = wasm.exports().opaJsonDump(addr);
var result = wasm.memory().readCString(resultStrAddr);
wasm.opaFree(resultStrAddr);
wasm.exports().opaFree(resultStrAddr);
return result;
}

// data MUST be a serializable object or ArrayBuffer, which assumed to be a well-formed
// stringified JSON
public OpaPolicy data(String data) {
wasm.opaHeapPtrSet(this.baseHeapPtr);
wasm.exports().opaHeapPtrSet(this.baseHeapPtr);
this.dataAddr = loadJson(data);
this.dataHeapPtr = wasm.opaHeapPtrGet();
this.dataHeapPtr = wasm.exports().opaHeapPtrGet();
return this;
}

Expand Down Expand Up @@ -110,7 +110,7 @@ public OpaPolicy input(String input) {

public Map<String, Integer> entrypoints() {
try {
var json = dumpJson(wasm.entrypoints());
var json = dumpJson(wasm.exports().entrypoints());
var entrypoints =
wasm.jsonMapper()
.readValue(json, new TypeReference<HashMap<String, Integer>>() {});
Expand All @@ -130,24 +130,24 @@ public int findEntrypoint(String name) {
}

public String evaluate() {
var ctxAddr = wasm.opaEvalCtxNew();
var ctxAddr = wasm.exports().opaEvalCtxNew();
if (this.dataAddr == -1) {
data("");
}
wasm.opaEvalCtxSetData(ctxAddr, this.dataAddr);
wasm.exports().opaEvalCtxSetData(ctxAddr, this.dataAddr);
if (this.inputAddr == -1) {
input("");
}
wasm.opaEvalCtxSetInput(ctxAddr, this.inputAddr);
wasm.opaEvalCtxSetEntrypoint(ctxAddr, this.entrypoint);
wasm.exports().opaEvalCtxSetInput(ctxAddr, this.inputAddr);
wasm.exports().opaEvalCtxSetEntrypoint(ctxAddr, this.entrypoint);

var evalResult = OpaErrorCode.fromValue(wasm.eval(ctxAddr));
var evalResult = OpaErrorCode.fromValue(wasm.exports().eval(ctxAddr));
if (evalResult != OpaErrorCode.OPA_ERR_OK) {
throw new RuntimeException(
"Error evaluating the Opa Policy, returned code is: " + evalResult);
}

this.resultAddr = wasm.opaEvalCtxGetResult(ctxAddr);
this.resultAddr = wasm.exports().opaEvalCtxGetResult(ctxAddr);
var result = dumpJson(resultAddr);
return result;
}
Expand Down Expand Up @@ -259,8 +259,7 @@ public OpaPolicy build() {
.withJsonMapper(jsonMapper)
.withYamlMapper(yamlMapper)
.withMemory(
new ByteBufferMemory(
new MemoryLimits(initialMemory, maxMemory)))
new ByteArrayMemory(new MemoryLimits(initialMemory, maxMemory)))
.withDefaultBuiltins(defaultBuiltins)
.addBuiltins(builtins.toArray(OpaBuiltin.Builtin[]::new))
.build();
Expand Down
36 changes: 21 additions & 15 deletions core/src/main/java/com/styra/opa/wasm/OpaWasm.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.styra.opa.wasm;

import com.dylibso.chicory.experimental.hostmodule.annotations.WasmModuleInterface;
import com.dylibso.chicory.runtime.ByteArrayMemory;
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.runtime.Memory;
import com.dylibso.chicory.wasm.Parser;
Expand All @@ -14,11 +13,12 @@
import java.util.List;

// Low level bindings to OPA
// The resulting code is the target to be generated by chicory-bindgen
@WasmModuleInterface("demo-policy.wasm")
public class OpaWasm implements OpaWasm_ModuleExports, OpaWasm_ModuleImports, OpaWasm_Env {
public class OpaWasm implements OpaWasm_ModuleImports, OpaWasm_Env {
private final Instance instance;
private final Memory memory;
private final OpaWasm_ModuleExports exports;

private final ObjectMapper jsonMapper;
private final ObjectMapper yamlMapper;
private final OpaBuiltin.Builtin[] builtins;
Expand All @@ -40,19 +40,20 @@ private OpaWasm(
this.instance =
Instance.builder(Parser.parse(is))
.withImportValues(toImportValues())
.withMemoryFactory(ByteArrayMemory::new)
.withMemoryFactory(limits -> memory)
.build();
this.exports = new OpaWasm_ModuleExports(instance);
this.builtins = initializeBuiltins(defaultBuiltins, builtins);
}

public OpaBuiltin.Builtin[] initializeBuiltins(
boolean defaultBuiltins, OpaBuiltin.Builtin[] builtins) {
var mappings = new HashMap<String, Integer>();
int builtinsAddr = builtins();
var builtinsStrAddr = opaJsonDump(builtinsAddr);
int builtinsAddr = exports.builtins();
var builtinsStrAddr = exports.opaJsonDump(builtinsAddr);
var builtinsStr = memory().readCString(builtinsStrAddr);
opaFree(builtinsStrAddr);
opaFree(builtinsAddr);
exports.opaFree(builtinsStrAddr);
exports.opaFree(builtinsAddr);
try {
var fields = jsonMapper().readTree(builtinsStr).fields();
while (fields.hasNext()) {
Expand Down Expand Up @@ -155,23 +156,23 @@ public Instance instance() {
return this.instance;
}

public Memory memory() {
return this.memory;
public OpaWasm_ModuleExports exports() {
return this.exports;
}

// helper functions - can be written by the end user
public String readString(int addr) {
int resultAddr = opaJsonDump(addr);
int resultAddr = exports.opaJsonDump(addr);
var resultStr = memory().readCString(resultAddr);
opaFree(resultAddr);
exports.opaFree(resultAddr);
return resultStr;
}

public int writeResult(String result) {
var resultStrAddr = opaMalloc(result.length());
var resultStrAddr = exports.opaMalloc(result.length());
memory().writeCString(resultStrAddr, result);
var resultAddr = opaJsonParse(resultStrAddr, result.length());
opaFree(resultStrAddr);
var resultAddr = exports.opaJsonParse(resultStrAddr, result.length());
exports.opaFree(resultStrAddr);
return resultAddr;
}

Expand All @@ -181,6 +182,11 @@ public void opaAbort(int ptr) {
throw new OpaAbortException("opa_abort - " + errorMessage);
}

@Override
public Memory memory() {
return memory;
}

@Override
public int opaBuiltin0(int builtinId, int ctx) {
return builtins[builtinId].asBuiltin0(this);
Expand Down
49 changes: 25 additions & 24 deletions core/src/test/java/com/styra/opa/wasm/OpaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,46 @@ public void lowLevelAPI() throws Exception {
.withMemory(new ByteBufferMemory(new MemoryLimits(2, 2)))
.withInputStream(new FileInputStream(wasmFile.toFile()))
.build();
var opaExports = opa.exports();

assertEquals(opa.opaWasmAbiVersion().getValue(), 1L);
assertEquals(opa.opaWasmAbiMinorVersion().getValue(), 3L);
assertEquals(opaExports.opaWasmAbiVersion().getValue(), 1L);
assertEquals(opaExports.opaWasmAbiMinorVersion().getValue(), 3L);

var builtinsAddr = opa.builtins();
var builtinsStringAddr = opa.opaJsonDump(builtinsAddr);
assertEquals("{}", opa.memory().readCString(builtinsStringAddr));
var builtinsAddr = opaExports.builtins();
var builtinsStringAddr = opaExports.opaJsonDump(builtinsAddr);
assertEquals("{}", opaExports.memory().readCString(builtinsStringAddr));

// Following the instructions here:
// https://www.openpolicyagent.org/docs/latest/wasm/#evaluation
var ctxAddr = opa.opaEvalCtxNew();
var ctxAddr = opaExports.opaEvalCtxNew();

var input = "{\"user\": \"alice\"}";
var inputStrAddr = opa.opaMalloc(input.length());
opa.memory().writeCString(inputStrAddr, input);
var inputAddr = opa.opaJsonParse(inputStrAddr, input.length());
opa.opaFree(inputStrAddr);
opa.opaEvalCtxSetInput(ctxAddr, inputAddr);
var inputStrAddr = opaExports.opaMalloc(input.length());
opaExports.memory().writeCString(inputStrAddr, input);
var inputAddr = opaExports.opaJsonParse(inputStrAddr, input.length());
opaExports.opaFree(inputStrAddr);
opaExports.opaEvalCtxSetInput(ctxAddr, inputAddr);

var data = "{ \"role\" : { \"alice\" : \"admin\", \"bob\" : \"user\" } }";
var dataStrAddr = opa.opaMalloc(data.length());
opa.memory().writeCString(dataStrAddr, data);
var dataAddr = opa.opaJsonParse(dataStrAddr, data.length());
opa.opaFree(dataStrAddr);
opa.opaEvalCtxSetData(ctxAddr, dataAddr);
var dataStrAddr = opaExports.opaMalloc(data.length());
opaExports.memory().writeCString(dataStrAddr, data);
var dataAddr = opaExports.opaJsonParse(dataStrAddr, data.length());
opaExports.opaFree(dataStrAddr);
opaExports.opaEvalCtxSetData(ctxAddr, dataAddr);

var evalResult = OpaErrorCode.fromValue(opa.eval(ctxAddr));
var evalResult = OpaErrorCode.fromValue(opaExports.eval(ctxAddr));
assertEquals(OpaErrorCode.OPA_ERR_OK, evalResult);

int resultAddr = opa.opaEvalCtxGetResult(ctxAddr);
int resultStrAddr = opa.opaJsonDump(resultAddr);
var resultStr = opa.memory().readCString(resultStrAddr);
opa.opaFree(resultStrAddr);
int resultAddr = opaExports.opaEvalCtxGetResult(ctxAddr);
int resultStrAddr = opaExports.opaJsonDump(resultAddr);
var resultStr = opaExports.memory().readCString(resultStrAddr);
opaExports.opaFree(resultStrAddr);
assertEquals("[{\"result\":true}]", resultStr);

// final cleanup of resources for demo purposes
opa.opaValueFree(inputAddr);
opa.opaValueFree(dataAddr);
opa.opaValueFree(resultAddr);
opaExports.opaValueFree(inputAddr);
opaExports.opaValueFree(dataAddr);
opaExports.opaValueFree(resultAddr);
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<maven-gpg-plugin.version>3.2.7</maven-gpg-plugin.version>
<nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<chicory.version>1.1.1</chicory.version>
<chicory.version>1.2.0</chicory.version>
<junit.version>5.12.1</junit.version>
<jackson.version>2.18.3</jackson.version>
<spotless.version>2.44.3</spotless.version>
Expand Down
Loading