Skip to content

Commit

Permalink
Merge pull request #228 from biscuit-auth/ffi
Browse files Browse the repository at this point in the history
datalog foreign function interface prototype
  • Loading branch information
divarvel authored Nov 19, 2024
2 parents 796ba5d + a179587 commit 4556320
Show file tree
Hide file tree
Showing 17 changed files with 958 additions and 168 deletions.
75 changes: 74 additions & 1 deletion biscuit-auth/examples/testcases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ use biscuit::macros::*;
use biscuit::Authorizer;
use biscuit::{builder::*, builder_ext::*, Biscuit};
use biscuit::{KeyPair, PrivateKey, PublicKey};
use biscuit_auth::builder;
use biscuit_auth::datalog::ExternFunc;
use biscuit_auth::datalog::RunLimits;
use prost::Message;
use rand::prelude::*;
use serde::Serialize;
use std::collections::HashMap;
use std::sync::Arc;
use std::{
collections::{BTreeMap, BTreeSet},
fs::File,
Expand Down Expand Up @@ -157,6 +162,9 @@ fn run(target: String, root_key: Option<String>, test: bool, json: bool) {
add_test_result(&mut results, type_of(&target, &root, test));

add_test_result(&mut results, array_map(&target, &root, test));

add_test_result(&mut results, ffi(&target, &root, test));

if json {
let s = serde_json::to_string_pretty(&TestCases {
root_private_key: hex::encode(root.private().to_bytes()),
Expand Down Expand Up @@ -297,6 +305,22 @@ enum AuthorizerResult {
}

fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validation {
validate_token_with_limits_and_external_functions(
root,
data,
authorizer_code,
RunLimits::default(),
Default::default(),
)
}

fn validate_token_with_limits_and_external_functions(
root: &KeyPair,
data: &[u8],
authorizer_code: &str,
run_limits: RunLimits,
extern_funcs: HashMap<String, ExternFunc>,
) -> Validation {
let token = match Biscuit::from(&data[..], &root.public()) {
Ok(t) => t,
Err(e) => {
Expand All @@ -316,6 +340,7 @@ fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validat
}

let mut authorizer = Authorizer::new();
authorizer.set_extern_funcs(extern_funcs);
authorizer.add_code(authorizer_code).unwrap();
let authorizer_code = authorizer.dump_code();

Expand All @@ -331,7 +356,7 @@ fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validat
}
};

let res = authorizer.authorize();
let res = authorizer.authorize_with_limits(run_limits);
//println!("authorizer world:\n{}", authorizer.print_world());
let (_, _, _, policies) = authorizer.dump();
let snapshot = authorizer.snapshot().unwrap();
Expand Down Expand Up @@ -2269,6 +2294,54 @@ fn array_map(target: &str, root: &KeyPair, test: bool) -> TestResult {
}
}

fn ffi(target: &str, root: &KeyPair, test: bool) -> TestResult {
let mut rng: StdRng = SeedableRng::seed_from_u64(1234);
let title = "test ffi calls (v6 blocks)".to_string();
let filename = "test035_ffi".to_string();
let token;

let biscuit =
biscuit!(r#"check if true.extern::test(), "a".extern::test("a") == "equal strings""#)
.build_with_rng(&root, SymbolTable::default(), &mut rng)
.unwrap();
token = print_blocks(&biscuit);

let data = write_or_load_testcase(target, &filename, root, &biscuit, test);

let mut validations = BTreeMap::new();
validations.insert(
"".to_string(),
validate_token_with_limits_and_external_functions(
root,
&data[..],
"allow if true",
RunLimits::default(),
HashMap::from([(
"test".to_string(),
ExternFunc::new(Arc::new(|left, right| match (left, right) {
(t, None) => Ok(t),
(builder::Term::Str(left), Some(builder::Term::Str(right)))
if left == right =>
{
Ok(builder::Term::Str("equal strings".to_string()))
}
(builder::Term::Str(_), Some(builder::Term::Str(_))) => {
Ok(builder::Term::Str("different strings".to_string()))
}
_ => Err("unsupported operands".to_string()),
})),
)]),
),
);

TestResult {
title,
filename,
token,
validations,
}
}

fn print_blocks(token: &Biscuit) -> Vec<BlockContent> {
let mut v = Vec::new();

Expand Down
48 changes: 48 additions & 0 deletions biscuit-auth/samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3139,3 +3139,51 @@ World {

result: `Ok(0)`


------------------------------

## test ffi calls (v6 blocks): test035_ffi.bc
### token

authority:
symbols: ["test", "a", "equal strings"]

public keys: []

```
check if true.extern::test(), "a".extern::test("a") == "equal strings";
```

### validation

authorizer code:
```
allow if true;
```

revocation ids:
- `faf26fe6f5dfa08c114a0a29321405b6fb7be79b0d80694d27925f7deb01effe5707600e42fd74f9a1d2920466446d51949155f4548f0fd68f3e9326c7e12404`

authorizer world:
```
World {
facts: []
rules: []
checks: [
Checks {
origin: Some(
0,
),
checks: [
"check if true.extern::test(), \"a\".extern::test(\"a\") == \"equal strings\"",
],
},
]
policies: [
"allow if true",
]
}
```

result: `Ok(0)`

42 changes: 42 additions & 0 deletions biscuit-auth/samples/samples.json
Original file line number Diff line number Diff line change
Expand Up @@ -2913,6 +2913,48 @@
]
}
}
},
{
"title": "test ffi calls (v6 blocks)",
"filename": "test035_ffi.bc",
"token": [
{
"symbols": [
"test",
"a",
"equal strings"
],
"public_keys": [],
"external_key": null,
"code": "check if true.extern::test(), \"a\".extern::test(\"a\") == \"equal strings\";\n"
}
],
"validations": {
"": {
"world": {
"facts": [],
"rules": [],
"checks": [
{
"origin": 0,
"checks": [
"check if true.extern::test(), \"a\".extern::test(\"a\") == \"equal strings\""
]
}
],
"policies": [
"allow if true"
]
},
"result": {
"Ok": 0
},
"authorizer_code": "allow if true;\n",
"revocation_ids": [
"faf26fe6f5dfa08c114a0a29321405b6fb7be79b0d80694d27925f7deb01effe5707600e42fd74f9a1d2920466446d51949155f4548f0fd68f3e9326c7e12404"
]
}
}
}
]
}
Binary file added biscuit-auth/samples/test035_ffi.bc
Binary file not shown.
Loading

0 comments on commit 4556320

Please sign in to comment.