forked from open-policy-agent/opa
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add C library implementing operations for WASM
These changes add a C library that implements low-level data operations and JSON parsing for WASM policies. The output of the WASM build process are checked into the repository so that OPA can easily access the bytecode for test and other purposes. Signed-off-by: Torin Sandall <[email protected]>
- Loading branch information
Showing
22 changed files
with
2,456 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ coverage | |
opa_* | ||
.Dockerfile_* | ||
_release | ||
wasm/_obj | ||
site.tar.gz | ||
policy.wasm | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2018 The OPA Authors. All rights reserved. | ||
// Use of this source code is governed by an Apache2 | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"fmt" | ||
"io" | ||
"os" | ||
"path" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
type params struct { | ||
Output string | ||
} | ||
|
||
func main() { | ||
|
||
var params params | ||
executable := path.Base(os.Args[0]) | ||
|
||
command := &cobra.Command{ | ||
Use: executable, | ||
Short: executable + " <opa.wasm path>", | ||
RunE: func(_ *cobra.Command, args []string) error { | ||
if len(args) != 1 { | ||
return fmt.Errorf("provide path of opa.wasm file") | ||
} | ||
return run(params, args) | ||
}, | ||
} | ||
|
||
command.Flags().StringVarP(¶ms.Output, "output", "o", "", "set path of output file (default: stdout)") | ||
|
||
if err := command.Execute(); err != nil { | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func run(params params, args []string) error { | ||
|
||
var out io.Writer | ||
|
||
if params.Output != "" { | ||
f, err := os.Create(params.Output) | ||
if err != nil { | ||
return err | ||
} | ||
defer f.Close() | ||
out = f | ||
} else { | ||
out = os.Stdout | ||
} | ||
|
||
_, err := out.Write([]byte(`// Copyright 2018 The OPA Authors. All rights reserved. | ||
// Use of this source code is governed by an Apache2 | ||
// license that can be found in the LICENSE file. | ||
// THIS FILE IS GENERATED. DO NOT EDIT. | ||
// Package opa contains bytecode for the OPA-WASM library. | ||
package opa | ||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"io/ioutil" | ||
) | ||
// Bytes returns the OPA-WASM bytecode. | ||
func Bytes() ([]byte, error) { | ||
gr, err := gzip.NewReader(bytes.NewBuffer(gzipped)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return ioutil.ReadAll(gr) | ||
} | ||
`)) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = out.Write([]byte(`var gzipped = []byte("`)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
in, err := os.Open(args[0]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer in.Close() | ||
|
||
var buf bytes.Buffer | ||
gw := gzip.NewWriter(&buf) | ||
_, err = io.Copy(gw, in) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
gw.Close() | ||
|
||
for _, b := range buf.Bytes() { | ||
if _, err := out.Write([]byte(`\x`)); err != nil { | ||
return err | ||
} | ||
if _, err := out.Write(asciihex(b)); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
_, err = out.Write([]byte(`")`)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = out.Write([]byte("\n")) | ||
return err | ||
} | ||
|
||
var digits = "0123456789ABCDEF" | ||
|
||
func asciihex(b byte) []byte { | ||
lo := digits[(b & 0x0F)] | ||
hi := digits[(b >> 4)] | ||
return []byte{hi, lo} | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
FROM ubuntu:18.04 | ||
|
||
RUN apt-get update && apt-get install -y curl git build-essential | ||
|
||
RUN bash -c 'echo -ne "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main\ndeb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" > /etc/apt/sources.list.d/llvm.list' | ||
|
||
RUN curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - | ||
|
||
RUN apt-get update && \ | ||
apt-get install -y \ | ||
cmake \ | ||
clang-8 \ | ||
lld-8 | ||
|
||
ENV CC=clang-8 | ||
ENV CXX=clang-8 | ||
ENV LLD=wasm-ld-8 | ||
ENV AR=llvm-ar-8 | ||
ENV RANLIB=llvm-ranlib-8 | ||
|
||
RUN ln -s /usr/bin/clang-8 /usr/bin/clang && \ | ||
ln -s /usr/bin/clang++-8 /usr/bin/clang++ && \ | ||
ln -s /usr/bin/clang-cpp-8 /usr/bin/clang-cpp | ||
|
||
RUN git clone https://github.com/WebAssembly/wabt && \ | ||
cd wabt && \ | ||
git checkout 1.0.5 && \ | ||
git submodule update --init && \ | ||
make | ||
|
||
ENV PATH="/wabt/out/clang/Debug:${PATH}" | ||
|
||
WORKDIR /src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
DOCKER := docker | ||
|
||
WASM_BUILDER_REPOSITORY := openpolicyagent/opa-wasm-builder | ||
WASM_BUILDER_VERSION := 1.0 | ||
WASM_BUILDER_IMAGE := $(WASM_BUILDER_REPOSITORY):$(WASM_BUILDER_VERSION) | ||
WASM_OBJ_DIR := _obj | ||
|
||
$(shell mkdir -p $(WASM_OBJ_DIR)) | ||
|
||
CFLAGS := \ | ||
-O3 \ | ||
-nostdinc \ | ||
-nodefaultlibs \ | ||
--target=wasm32-unknown-unknown-wasm | ||
|
||
.PHONY: all | ||
all: build test | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -fr $(WASM_OBJ_DIR) | ||
|
||
.PHONY: builder | ||
builder: Dockerfile | ||
@$(DOCKER) build -t $(WASM_BUILDER_IMAGE) -f Dockerfile . | ||
|
||
.PHONY: build | ||
build: | ||
@$(DOCKER) run -it --rm -v $(CURDIR):/src $(WASM_BUILDER_IMAGE) make $(WASM_OBJ_DIR)/opa.wasm | ||
|
||
.PHONY: test | ||
test: | ||
@$(DOCKER) run -it --rm -v $(CURDIR):/src $(WASM_BUILDER_IMAGE) make $(WASM_OBJ_DIR)/opa-test.wasm | ||
@$(DOCKER) run -it --rm -e VERBOSE=$(VERBOSE) -v $(CURDIR):/src -w /src node:8 node test.js $(WASM_OBJ_DIR)/opa-test.wasm | ||
|
||
.PHONY: hack | ||
hack: | ||
@$(DOCKER) run -it --rm -v $(CURDIR):/src $(WASM_BUILDER_IMAGE) | ||
|
||
$(WASM_OBJ_DIR)/malloc.wasm: src/malloc.c | ||
@$(CC) $(CFLAGS) -c $^ -o $@ | ||
|
||
$(WASM_OBJ_DIR)/string.wasm: src/string.c | ||
@$(CC) $(CFLAGS) -c $^ -o $@ | ||
|
||
$(WASM_OBJ_DIR)/json.wasm: src/json.c | ||
@$(CC) $(CFLAGS) -c $^ -o $@ | ||
|
||
$(WASM_OBJ_DIR)/value.wasm: src/value.c | ||
@$(CC) $(CFLAGS) -c $^ -o $@ | ||
|
||
$(WASM_OBJ_DIR)/opa.wasm: $(WASM_OBJ_DIR)/malloc.wasm \ | ||
$(WASM_OBJ_DIR)/value.wasm \ | ||
$(WASM_OBJ_DIR)/string.wasm \ | ||
$(WASM_OBJ_DIR)/json.wasm | ||
@wasm-ld-8 \ | ||
--allow-undefined-file=src/undefined.symbols \ | ||
--import-memory \ | ||
--no-entry \ | ||
--export-all \ | ||
$^ \ | ||
-o $@ | ||
@wasm2wat $(WASM_OBJ_DIR)/opa.wasm > $(WASM_OBJ_DIR)/opa.wast | ||
|
||
$(WASM_OBJ_DIR)/test.wasm: tests/test.c | ||
@$(CC) $(CFLAGS) -I src -c $^ -o $@ | ||
|
||
$(WASM_OBJ_DIR)/opa-test.wasm: $(WASM_OBJ_DIR)/test.wasm \ | ||
$(WASM_OBJ_DIR)/malloc.wasm \ | ||
$(WASM_OBJ_DIR)/value.wasm \ | ||
$(WASM_OBJ_DIR)/string.wasm \ | ||
$(WASM_OBJ_DIR)/json.wasm | ||
@wasm-ld-8 \ | ||
--allow-undefined-file=tests/undefined.symbols \ | ||
--import-memory \ | ||
--no-entry \ | ||
--export-all \ | ||
$^ \ | ||
-o $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# OPA-WASM | ||
|
||
This directory contains a library that implements various low-level | ||
operations for policies compiled into WebAssembly (WASM). Specifically, the | ||
library implements: | ||
|
||
* JSON parsing | ||
* JSON AST (e.g., comparison, iteration, lookup, etc.) | ||
* String operations | ||
* Memory allocation | ||
|
||
This library does not make any backwards compatibility guarantees. | ||
|
||
## Development | ||
|
||
You should have Docker installed to build and test changes to the library. We | ||
commit the output of the build (`opa.wasm`) into the repository so it's | ||
important for the build output to be reproducible. | ||
|
||
You can build the library by running `make build`. This will produce WASM | ||
executables under the `_obj` directory. | ||
|
||
You can test the library by running `make test`. By default the test runner | ||
does not print messages when tests pass. If you run `make test VERBOSE=1` it | ||
will log all of the tests that were run. | ||
|
||
You can run `make hack` to start a shell inside the builder image. This is | ||
useful if you need to interact with low-level WASM tooling like | ||
`wasm-objdump`, `wasm2wat`, etc. or LLVM itself. | ||
|
||
You must manually push the builder image if you make changes to it (run `make | ||
builder` to produce a new Docker image). | ||
|
||
## Vendoring | ||
|
||
If you make changes to the library, run the `make generate` in the parent | ||
directory and commit the results back to the repository. The `generate` | ||
target will: | ||
|
||
1. Build the OPA-WASM library | ||
2. Copy the library into the [internal/compiler/wasm/opa](../internal/compiler/wasm/opa) directory. | ||
3. Run the tool to generate the [internal/compiler/wasm/opa/opa.go](../internal/compiler/wasm/opa/opa.go) file. |
Oops, something went wrong.