mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
c_no_std binding to show use in C freestanding environments. (#238)
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
5422bde391
commit
67f65c0561
5
.gitignore
vendored
5
.gitignore
vendored
@@ -13,4 +13,7 @@ Cargo.lock
|
||||
.vscode/
|
||||
|
||||
# worktrees
|
||||
worktrees/
|
||||
worktrees/
|
||||
|
||||
# build folders
|
||||
**/build
|
||||
@@ -121,7 +121,7 @@ jsonwebtoken = { version = "9.2.0", optional = true }
|
||||
itertools = { version = "0.12.1", default-features = false, optional = true }
|
||||
|
||||
serde_yaml = {version = "0.9.16", default-features = false, optional = true }
|
||||
rand = { version = "0.8.5", default-features = false, optional = true }
|
||||
rand = { version = "0.8.5", default-features = false, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.45"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
Regorus is also
|
||||
- *cross-platform* - Written in platform-agnostic Rust.
|
||||
- *no_std compatible* - Regorus can be used in `no_std` environments too. Most of the builtins are supported.
|
||||
- *current* - We strive to keep Regorus up to date with latest OPA release. Regorus supports `import rego.v1`.
|
||||
- *compliant* - Regorus is mostly compliant with the latest [OPA release v0.64.0](https://github.com/open-policy-agent/opa/releases/tag/v0.64.0). See [OPA Conformance](#opa-conformance) for details. Note that while we behaviorally produce the same results, we don't yet support all the builtins.
|
||||
- *extensible* - Extend the Rego language by implementing custom stateful builtins in Rust.
|
||||
@@ -85,7 +86,7 @@ Regorus is designed with [Confidential Computing](https://confidentialcomputing.
|
||||
it is important to be able to control exactly what is being run. Regorus allows enabling and disabling various components using cargo
|
||||
features. By default all features are enabled.
|
||||
|
||||
The default build of regorus example program is 6.4M:
|
||||
The default build of regorus example program is 6.3M:
|
||||
```bash
|
||||
$ cargo build -r --example regorus; strip target/release/examples/regorus; ls -lh target/release/examples/regorus
|
||||
-rwxr-xr-x 1 anand staff 6.3M May 11 22:03 target/release/examples/regorus*
|
||||
@@ -108,6 +109,7 @@ Regorus can be used from a variety of languages:
|
||||
- *C*: C binding is generated using [cbindgen](https://github.com/mozilla/cbindgen).
|
||||
[corrosion-rs](https://github.com/corrosion-rs/corrosion) can be used to seamlessly use Regorous
|
||||
in your CMake based projects. See [bindings/c](https://github.com/microsoft/regorus/tree/main/bindings/c).
|
||||
- *C freestanding*: [bindings/c_no_std](https://github.com/microsoft/regorus/tree/main/bindings/c_no_std) shows how to use Regorus from C environments without a libc.
|
||||
- *C++*: C++ binding is generated using [cbindgen](https://github.com/mozilla/cbindgen).
|
||||
[corrosion-rs](https://github.com/corrosion-rs/corrosion) can be used to seamlessly use Regorous
|
||||
in your CMake based projects. See [bindings/cpp](https://github.com/microsoft/regorus/tree/main/bindings/cpp).
|
||||
|
||||
41
bindings/c-nostd/CMakeLists.txt
Normal file
41
bindings/c-nostd/CMakeLists.txt
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) Microsoft
|
||||
# Licensed under the MIT License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
Corrosion
|
||||
GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
|
||||
GIT_TAG v0.4 # Optionally specify a commit hash, version tag or branch here
|
||||
)
|
||||
FetchContent_MakeAvailable(Corrosion)
|
||||
|
||||
project("regorus-test")
|
||||
|
||||
corrosion_import_crate(
|
||||
# Path to <regorus-source-folder>/bindings/ffi/Cargo.toml
|
||||
MANIFEST_PATH "../ffi/Cargo.toml"
|
||||
# Always build regorus in Release mode.
|
||||
PROFILE "release"
|
||||
# Only build the "regorus-ffi" crate.
|
||||
CRATES "regorus-ffi"
|
||||
|
||||
# Turn off std support in regorus-ffi.
|
||||
NO_DEFAULT_FEATURES
|
||||
NO_STD
|
||||
|
||||
# custom_allocator allows using a custom memory allocator.
|
||||
# To use malloc/free remove custom_allocator below.
|
||||
# Additionally, select specific features in regorus.
|
||||
# See regorus/opa_no_std
|
||||
FEATURES "custom_allocator,regorus/semver"
|
||||
|
||||
# Link statically
|
||||
CRATE_TYPES staticlib FLAGS --crate-type=staticlib
|
||||
)
|
||||
|
||||
add_executable(regorus_test_nostd main.c)
|
||||
# Add path to <regorus-source-folder>/bindings/ffi
|
||||
target_include_directories(regorus_test_nostd PRIVATE "../ffi")
|
||||
target_link_libraries(regorus_test_nostd regorus-ffi)
|
||||
96
bindings/c-nostd/main.c
Normal file
96
bindings/c-nostd/main.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <stdio.h>
|
||||
#include "regorus.h"
|
||||
|
||||
|
||||
// Regorus has been built for no_std and cannot access files.
|
||||
char* file_to_string(const char* file) {
|
||||
char * buffer = 0;
|
||||
long length;
|
||||
FILE * f = fopen (file, "rb");
|
||||
|
||||
if (f)
|
||||
{
|
||||
fseek (f, 0, SEEK_END);
|
||||
length = ftell (f);
|
||||
fseek (f, 0, SEEK_SET);
|
||||
buffer = malloc (length);
|
||||
if (buffer)
|
||||
{
|
||||
fread (buffer, 1, length, f);
|
||||
}
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// If regorus is built with custom-allocator, then provide implementation.
|
||||
uint8_t* regorus_aligned_alloc(size_t alignment, size_t size) {
|
||||
printf("%ld %ld\n", size, alignment);
|
||||
fflush(stdout);
|
||||
return aligned_alloc(alignment, size);
|
||||
}
|
||||
|
||||
void regorus_free(uint8_t* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
// Create engine.
|
||||
RegorusEngine* engine = regorus_engine_new();
|
||||
RegorusResult r;
|
||||
char* buffer = NULL;
|
||||
|
||||
// Load policies.
|
||||
r = regorus_engine_add_policy(engine, "framework.rego", (buffer = file_to_string("../../../tests/aci/framework.rego")));
|
||||
free(buffer);
|
||||
if (r.status != RegorusStatusOk)
|
||||
goto error;
|
||||
regorus_result_drop(r);
|
||||
|
||||
r = regorus_engine_add_policy(engine, "api.rego", (buffer = file_to_string("../../../tests/aci/api.rego")));
|
||||
free(buffer);
|
||||
if (r.status != RegorusStatusOk)
|
||||
goto error;
|
||||
regorus_result_drop(r);
|
||||
|
||||
r = regorus_engine_add_policy(engine, "policy.rego", (buffer = file_to_string("../../../tests/aci/policy.rego")));
|
||||
free(buffer);
|
||||
if (r.status != RegorusStatusOk)
|
||||
goto error;
|
||||
regorus_result_drop(r);
|
||||
|
||||
// Add data
|
||||
r = regorus_engine_add_data_json(engine, (buffer = file_to_string("../../../tests/aci/data.json")));
|
||||
free(buffer);
|
||||
if (r.status != RegorusStatusOk)
|
||||
goto error;
|
||||
regorus_result_drop(r);
|
||||
|
||||
// Set input
|
||||
r = regorus_engine_set_input_json(engine, (buffer = file_to_string("../../../tests/aci/input.json")));
|
||||
free(buffer);
|
||||
if (r.status != RegorusStatusOk)
|
||||
goto error;
|
||||
regorus_result_drop(r);
|
||||
|
||||
// Eval query
|
||||
r = regorus_engine_eval_query(engine, "data.framework.mount_overlay=x");
|
||||
if (r.status != RegorusStatusOk)
|
||||
goto error;
|
||||
|
||||
// Print output
|
||||
printf("%s", r.output);
|
||||
regorus_result_drop(r);
|
||||
|
||||
|
||||
// Free the engine.
|
||||
regorus_engine_drop(engine);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
printf("%s", r.error_message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -18,8 +18,15 @@ corrosion_import_crate(
|
||||
MANIFEST_PATH "../ffi/Cargo.toml"
|
||||
# Always build regorus in Release mode.
|
||||
PROFILE "release"
|
||||
# Only build the "regorusc" crate.
|
||||
CRATES "regorus-ffi")
|
||||
# Only build the "regorus-ffi" crate.
|
||||
CRATES "regorus-ffi"
|
||||
|
||||
# Select specific features in regorus.
|
||||
FEATURES "regorus/semver"
|
||||
|
||||
# Link statically
|
||||
CRATE_TYPES "staticlib"
|
||||
)
|
||||
|
||||
add_executable(regorus_test main.c)
|
||||
# Add path to <regorus-source-folder>/bindings/ffi
|
||||
|
||||
@@ -5,13 +5,18 @@ edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
regorus = { path = "../.." }
|
||||
regorus = { path = "../..", default-features = false }
|
||||
serde_json = "1.0.113"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["regorus/std"]
|
||||
custom_allocator = []
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.26.0"
|
||||
csbindgen = "1.9.0"
|
||||
|
||||
@@ -85,4 +85,3 @@ namespace RegorusFFI
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -137,9 +137,6 @@ bitflags = false
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############## Options for How Your Rust library Should Be Parsed ##############
|
||||
|
||||
[parse]
|
||||
@@ -154,5 +151,5 @@ extra_bindings = []
|
||||
[parse.expand]
|
||||
crates = []
|
||||
all_features = false
|
||||
default_features = true
|
||||
default_features = false
|
||||
features = []
|
||||
@@ -90,6 +90,10 @@ RegorusResult regorus_engine_set_input_from_json_file(RegorusEngine *engine, con
|
||||
/// * `query`: Rego expression to be evaluate.
|
||||
RegorusResult regorus_engine_eval_query(RegorusEngine *engine, const char *query);
|
||||
|
||||
extern uint8_t *regorus_aligned_alloc(uintptr_t alignment, uintptr_t size);
|
||||
|
||||
extern void regorus_free(uint8_t *ptr);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // REGORUS_FFI_HPP
|
||||
|
||||
@@ -124,4 +124,8 @@ struct RegorusResult regorus_engine_set_input_from_json_file(struct RegorusEngin
|
||||
*/
|
||||
struct RegorusResult regorus_engine_eval_query(struct RegorusEngine *engine, const char *query);
|
||||
|
||||
extern uint8_t *regorus_aligned_alloc(uintptr_t alignment, uintptr_t size);
|
||||
|
||||
extern void regorus_free(uint8_t *ptr);
|
||||
|
||||
#endif /* REGORUS_H */
|
||||
|
||||
@@ -127,7 +127,6 @@ pub extern "C" fn regorus_engine_drop(engine: *mut RegorusEngine) {
|
||||
///
|
||||
/// * `path`: A filename to be associated with the policy.
|
||||
/// * `rego`: Rego policy.
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_add_policy(
|
||||
engine: *mut RegorusEngine,
|
||||
@@ -141,6 +140,7 @@ pub extern "C" fn regorus_engine_add_policy(
|
||||
}())
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_add_policy_from_file(
|
||||
engine: *mut RegorusEngine,
|
||||
@@ -169,6 +169,7 @@ pub extern "C" fn regorus_engine_add_data_json(
|
||||
}())
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_add_data_from_json_file(
|
||||
engine: *mut RegorusEngine,
|
||||
@@ -209,6 +210,7 @@ pub extern "C" fn regorus_engine_set_input_json(
|
||||
}())
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_set_input_from_json_file(
|
||||
engine: *mut RegorusEngine,
|
||||
@@ -246,3 +248,32 @@ pub extern "C" fn regorus_engine_eval_query(
|
||||
Err(e) => to_regorus_result(Err(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "custom_allocator")]
|
||||
extern "C" {
|
||||
fn regorus_aligned_alloc(alignment: usize, size: usize) -> *mut u8;
|
||||
fn regorus_free(ptr: *mut u8);
|
||||
}
|
||||
|
||||
#[cfg(feature = "custom_allocator")]
|
||||
mod allocator {
|
||||
use std::alloc::{GlobalAlloc, Layout};
|
||||
|
||||
struct RegorusAllocator {}
|
||||
|
||||
unsafe impl GlobalAlloc for RegorusAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
let size = layout.size();
|
||||
let align = layout.align();
|
||||
|
||||
crate::regorus_aligned_alloc(align, size)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
crate::regorus_free(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: RegorusAllocator = RegorusAllocator {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user