From 22fec4cb875ea90ec97620f8c7153fd795d7f479 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 21 Nov 2024 15:53:51 +0100 Subject: [PATCH 1/2] remove previous_key from ThirdPartyBlockRequest Same as for `legacyPublicKeys`, it is now deprecated and should not be set. It is kept in the schema to allow implementations to make sure it is not set. --- biscuit-auth/src/format/schema.proto | 2 +- biscuit-auth/src/format/schema.rs | 4 +- biscuit-auth/src/token/third_party.rs | 57 +++++++++++++++++---------- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/biscuit-auth/src/format/schema.proto b/biscuit-auth/src/format/schema.proto index 6aa760ac..21a13edd 100644 --- a/biscuit-auth/src/format/schema.proto +++ b/biscuit-auth/src/format/schema.proto @@ -217,7 +217,7 @@ message AuthorizerPolicies { } message ThirdPartyBlockRequest { - required PublicKey legacyPreviousKey = 1; + optional PublicKey legacyPreviousKey = 1; repeated PublicKey legacyPublicKeys = 2; required bytes previousSignature = 3; diff --git a/biscuit-auth/src/format/schema.rs b/biscuit-auth/src/format/schema.rs index 2de0ea42..d5d2c3c4 100644 --- a/biscuit-auth/src/format/schema.rs +++ b/biscuit-auth/src/format/schema.rs @@ -334,8 +334,8 @@ pub struct AuthorizerPolicies { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ThirdPartyBlockRequest { - #[prost(message, required, tag="1")] - pub legacy_previous_key: PublicKey, + #[prost(message, optional, tag="1")] + pub legacy_previous_key: ::core::option::Option, #[prost(message, repeated, tag="2")] pub legacy_public_keys: ::prost::alloc::vec::Vec, #[prost(bytes="vec", required, tag="3")] diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index 32048a98..e5b7ea62 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -4,7 +4,7 @@ use prost::Message; use crate::{ builder::BlockBuilder, - crypto::{generate_external_signature_payload_v1, PublicKey}, + crypto::generate_external_signature_payload_v1, datalog::SymbolTable, error, format::{convert::token_block_to_proto_block, schema, SerializedBiscuit}, @@ -14,9 +14,8 @@ use crate::{ use super::THIRD_PARTY_SIGNATURE_VERSION; /// Third party block request -#[derive(Debug)] +#[derive(PartialEq, Debug)] pub struct ThirdPartyRequest { - pub(crate) legacy_previous_key: PublicKey, pub(crate) previous_signature: Vec, } @@ -28,12 +27,6 @@ impl ThirdPartyRequest { return Err(error::Token::AppendOnSealed); } - let legacy_previous_key = container - .blocks - .last() - .unwrap_or(&container.authority) - .next_key; - let previous_signature = container .blocks .last() @@ -41,18 +34,14 @@ impl ThirdPartyRequest { .signature .to_bytes() .to_vec(); - Ok(ThirdPartyRequest { - legacy_previous_key, - previous_signature, - }) + Ok(ThirdPartyRequest { previous_signature }) } pub fn serialize(&self) -> Result, error::Token> { - let legacy_previous_key = self.legacy_previous_key.to_proto(); let previous_signature = self.previous_signature.clone(); let request = schema::ThirdPartyBlockRequest { - legacy_previous_key, + legacy_previous_key: None, legacy_public_keys: Vec::new(), previous_signature, }; @@ -75,20 +64,21 @@ impl ThirdPartyRequest { error::Format::DeserializationError(format!("deserialization error: {:?}", e)) })?; - let legacy_previous_key = PublicKey::from_proto(&data.legacy_previous_key)?; - if !data.legacy_public_keys.is_empty() { return Err(error::Token::Format(error::Format::DeserializationError( "public keys were provided in third-party block request".to_owned(), ))); } + if data.legacy_previous_key.is_some() { + return Err(error::Token::Format(error::Format::DeserializationError( + "previous public key was provided in third-party block request".to_owned(), + ))); + } + let previous_signature = data.previous_signature.to_vec(); - Ok(ThirdPartyRequest { - legacy_previous_key, - previous_signature, - }) + Ok(ThirdPartyRequest { previous_signature }) } pub fn deserialize_base64(slice: T) -> Result @@ -160,3 +150,28 @@ impl ThirdPartyBlock { Ok(base64::encode_config(self.serialize()?, base64::URL_SAFE)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn third_party_request_roundtrip() { + let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0); + let root = KeyPair::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); + let mut builder = crate::Biscuit::builder(); + + builder.add_fact("right(\"file1\", \"read\")").unwrap(); + builder.add_fact("right(\"file2\", \"read\")").unwrap(); + builder.add_fact("right(\"file1\", \"write\")").unwrap(); + + let biscuit1 = builder + .build_with_rng(&root, crate::token::default_symbol_table(), &mut rng) + .unwrap(); + let req = biscuit1.third_party_request().unwrap(); + let serialized_req = req.serialize().unwrap(); + let parsed_req = ThirdPartyRequest::deserialize(&serialized_req).unwrap(); + + assert_eq!(req, parsed_req); + } +} From 6ad363f3ca42b2912b9af47c8bad9f16144fe3c0 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Thu, 21 Nov 2024 16:30:57 +0100 Subject: [PATCH 2/2] display block version in samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this exposes a new public method on `Biscuit` and `UnverifiedBiscuit` to get a block’s version, same as printing a block contents or getting its external key. Exposing it on `UnverifiedBiscuit` will be useful for biscuit-cli --- biscuit-auth/examples/testcases.rs | 3 + biscuit-auth/samples/README.md | 124 ++++++++++++++++++ biscuit-auth/samples/samples.json | 186 ++++++++++++++++++--------- biscuit-auth/src/token/mod.rs | 31 +++++ biscuit-auth/src/token/unverified.rs | 5 + 5 files changed, 287 insertions(+), 62 deletions(-) diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index 84745859..d8a33d9f 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -213,6 +213,7 @@ struct BlockContent { pub public_keys: Vec, pub external_key: Option, pub code: String, + pub version: u32, } #[derive(Debug, Serialize)] @@ -243,6 +244,7 @@ impl TestResult { if let Some(key) = &block.external_key { writeln!(&mut s, "external signature by: {:?}\n", key); } + writeln!(&mut s, "block version: {}\n", block.version); writeln!(&mut s, "```\n{}```\n", block.code); } @@ -2431,6 +2433,7 @@ fn print_blocks(token: &Biscuit) -> Vec { .map(|k| k.print()) .collect(), external_key: token.block_external_key(i).unwrap().map(|k| k.print()), + version: token.block_version(i).unwrap(), }); } diff --git a/biscuit-auth/samples/README.md b/biscuit-auth/samples/README.md index 64c630f5..0d378295 100644 --- a/biscuit-auth/samples/README.md +++ b/biscuit-auth/samples/README.md @@ -13,6 +13,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -24,6 +26,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -96,6 +100,8 @@ symbols: ["file1"] public keys: [] +block version: 3 + ``` right("file1", "read"); ``` @@ -105,6 +111,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -124,6 +132,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -135,6 +145,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -154,6 +166,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -165,6 +179,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -184,6 +200,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -195,6 +213,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -214,6 +234,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -225,6 +247,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -234,6 +258,8 @@ symbols: [] public keys: [] +block version: 3 + ``` check if resource("file1"); ``` @@ -253,6 +279,8 @@ symbols: ["user_id", "alice", "file1"] public keys: [] +block version: 3 + ``` user_id("alice"); owner("alice", "file1"); @@ -263,6 +291,8 @@ symbols: ["0", "1"] public keys: [] +block version: 3 + ``` right($0, "read") <- resource($0), user_id($1), owner($1, $0); check if resource($0), operation("read"), right($0, "read"); @@ -273,6 +303,8 @@ symbols: ["file2"] public keys: [] +block version: 3 + ``` owner("alice", "file2"); ``` @@ -366,6 +398,8 @@ symbols: ["file1"] public keys: [] +block version: 3 + ``` right("file1", "read"); ``` @@ -375,6 +409,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -384,6 +420,8 @@ symbols: ["file2"] public keys: [] +block version: 3 + ``` right("file2", "read"); ``` @@ -467,6 +505,8 @@ symbols: [] public keys: [] +block version: 3 + ``` ``` @@ -475,6 +515,8 @@ symbols: ["file1"] public keys: [] +block version: 3 + ``` check if resource("file1"); check if time($time), $time <= 2018-12-20T00:00:00Z; @@ -541,6 +583,8 @@ symbols: ["file1"] public keys: [] +block version: 3 + ``` right("file1", "read"); ``` @@ -550,6 +594,8 @@ symbols: ["file2"] public keys: [] +block version: 3 + ``` right("file2", "read"); ``` @@ -634,6 +680,8 @@ symbols: ["file1"] public keys: [] +block version: 3 + ``` right("file1", "read"); ``` @@ -707,6 +755,8 @@ symbols: ["file1"] public keys: [] +block version: 3 + ``` check if resource("file1"); ``` @@ -813,6 +863,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -823,6 +875,8 @@ symbols: ["valid_date", "0", "1"] public keys: [] +block version: 3 + ``` valid_date("file1") <- time($0), resource("file1"), $0 <= 2030-12-31T12:59:59Z; valid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{"file1"}.contains($1); @@ -986,6 +1040,8 @@ symbols: ["0", "file[0-9]+.txt"] public keys: [] +block version: 3 + ``` check if resource($0), $0.matches("file[0-9]+.txt"); ``` @@ -1088,6 +1144,8 @@ symbols: ["must_be_present", "hello"] public keys: [] +block version: 3 + ``` must_be_present("hello"); ``` @@ -1149,6 +1207,8 @@ symbols: ["hello"] public keys: [] +block version: 3 + ``` check if resource("hello"); ``` @@ -1158,6 +1218,8 @@ symbols: ["test"] public keys: [] +block version: 3 + ``` query("test"); ``` @@ -1218,6 +1280,8 @@ symbols: ["hello world", "hello", "world", "aaabde", "a*c?.e", "abd", "aaa", "b" public keys: [] +block version: 3 + ``` check if true; check if !false; @@ -1340,6 +1404,8 @@ symbols: [] public keys: [] +block version: 3 + ``` check if operation("read"); ``` @@ -1349,6 +1415,8 @@ symbols: ["unbound", "any1", "any2"] public keys: [] +block version: 3 + ``` operation($unbound, "read") <- operation($any1, $any2); ``` @@ -1368,6 +1436,8 @@ symbols: [] public keys: [] +block version: 3 + ``` check if operation("read"); ``` @@ -1377,6 +1447,8 @@ symbols: ["any"] public keys: [] +block version: 3 + ``` operation("read") <- operation($any); ``` @@ -1457,6 +1529,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -1468,6 +1542,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` @@ -1542,6 +1618,8 @@ symbols: ["ns::fact_123", "hello é\t😁"] public keys: [] +block version: 3 + ``` ns::fact_123("hello é 😁"); ``` @@ -1603,6 +1681,8 @@ symbols: [] public keys: [] +block version: 3 + ``` read(0); write(1); @@ -1718,6 +1798,8 @@ symbols: ["authority_fact"] public keys: [] +block version: 3 + ``` authority_fact(1); ``` @@ -1727,6 +1809,8 @@ symbols: ["block1_fact"] public keys: [] +block version: 3 + ``` block1_fact(1); ``` @@ -1736,6 +1820,8 @@ symbols: ["var"] public keys: [] +block version: 3 + ``` check if authority_fact($var); check if block1_fact($var); @@ -1809,6 +1895,8 @@ symbols: [] public keys: ["ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189"] +block version: 4 + ``` right("read"); check if group("admin") trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189; @@ -1821,6 +1909,8 @@ public keys: [] external signature by: "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" +block version: 5 + ``` group("admin"); check if right("read"); @@ -1900,6 +1990,8 @@ symbols: ["allowed_operations", "A", "B", "op", "allowed"] public keys: [] +block version: 4 + ``` allowed_operations({"A", "B"}); check all operation($op), allowed_operations($allowed), $allowed.contains($op); @@ -2027,6 +2119,8 @@ symbols: [] public keys: ["ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189"] +block version: 4 + ``` query(0); check if true trusting previous, ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189; @@ -2039,6 +2133,8 @@ public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7 external signature by: "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" +block version: 5 + ``` query(1); query(1, 2) <- query(1), query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463; @@ -2053,6 +2149,8 @@ public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7 external signature by: "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463" +block version: 5 + ``` query(2); check if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463; @@ -2066,6 +2164,8 @@ public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7 external signature by: "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463" +block version: 5 + ``` query(3); check if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463; @@ -2077,6 +2177,8 @@ symbols: [] public keys: ["ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", "ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136"] +block version: 4 + ``` query(4); check if query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463; @@ -2256,6 +2358,8 @@ symbols: [] public keys: [] +block version: 4 + ``` check if 10000000000 * 10000000000 !== 0; check if 9223372036854775807 + 1 !== 0; @@ -2308,6 +2412,8 @@ symbols: ["abcD12x", "abcD12"] public keys: [] +block version: 4 + ``` check if 1 !== 3; check if 1 | 2 ^ 3 === 0; @@ -2366,6 +2472,8 @@ symbols: ["test"] public keys: [] +block version: 6 + ``` reject if test($test), $test; ``` @@ -2468,6 +2576,8 @@ symbols: ["fact", "value"] public keys: [] +block version: 6 + ``` check if fact(null, $value), $value == null; reject if fact(null, $value), $value != null; @@ -2661,6 +2771,8 @@ symbols: ["abcD12", "abcD12x", "fact", "value", "fact2"] public keys: [] +block version: 6 + ``` check if true == true; check if false == false; @@ -2837,6 +2949,8 @@ symbols: ["x", "p", "q"] public keys: [] +block version: 6 + ``` check if !false && true; check if false || true; @@ -2944,6 +3058,8 @@ symbols: ["integer", "string", "test", "date", "bytes", "bool", "set", "null", " public keys: [] +block version: 6 + ``` integer(1); string("test"); @@ -3050,6 +3166,8 @@ symbols: ["a", "b", "c", "p", "d", "A", "kv", "id", "roles"] public keys: [] +block version: 6 + ``` check if [1, 2, 1].length() == 3; check if ["a", "b"] != true; @@ -3150,6 +3268,8 @@ symbols: ["test", "a", "equal strings"] public keys: [] +block version: 6 + ``` check if true.extern::test(), "a".extern::test("a") == "equal strings"; ``` @@ -3198,6 +3318,8 @@ symbols: ["file1", "file2"] public keys: [] +block version: 3 + ``` right("file1", "read"); right("file2", "read"); @@ -3209,6 +3331,8 @@ symbols: ["0"] public keys: [] +block version: 3 + ``` check if resource($0), operation("read"), right($0, "read"); ``` diff --git a/biscuit-auth/samples/samples.json b/biscuit-auth/samples/samples.json index f52dd5e2..539d5e18 100644 --- a/biscuit-auth/samples/samples.json +++ b/biscuit-auth/samples/samples.json @@ -13,7 +13,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -21,7 +22,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { @@ -98,7 +100,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\n" + "code": "right(\"file1\", \"read\");\n", + "version": 3 }, { "symbols": [ @@ -106,7 +109,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { @@ -137,7 +141,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -145,7 +150,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { @@ -174,7 +180,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -182,7 +189,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { @@ -213,7 +221,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -221,7 +230,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { @@ -252,7 +262,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -260,13 +271,15 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 }, { "symbols": [], "public_keys": [], "external_key": null, - "code": "check if resource(\"file1\");\n" + "code": "check if resource(\"file1\");\n", + "version": 3 } ], "validations": { @@ -298,7 +311,8 @@ ], "public_keys": [], "external_key": null, - "code": "user_id(\"alice\");\nowner(\"alice\", \"file1\");\n" + "code": "user_id(\"alice\");\nowner(\"alice\", \"file1\");\n", + "version": 3 }, { "symbols": [ @@ -307,7 +321,8 @@ ], "public_keys": [], "external_key": null, - "code": "right($0, \"read\") <- resource($0), user_id($1), owner($1, $0);\ncheck if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "right($0, \"read\") <- resource($0), user_id($1), owner($1, $0);\ncheck if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 }, { "symbols": [ @@ -315,7 +330,8 @@ ], "public_keys": [], "external_key": null, - "code": "owner(\"alice\", \"file2\");\n" + "code": "owner(\"alice\", \"file2\");\n", + "version": 3 } ], "validations": { @@ -408,7 +424,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\n" + "code": "right(\"file1\", \"read\");\n", + "version": 3 }, { "symbols": [ @@ -416,7 +433,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 }, { "symbols": [ @@ -424,7 +442,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file2\", \"read\");\n" + "code": "right(\"file2\", \"read\");\n", + "version": 3 } ], "validations": { @@ -507,7 +526,8 @@ "symbols": [], "public_keys": [], "external_key": null, - "code": "" + "code": "", + "version": 3 }, { "symbols": [ @@ -515,7 +535,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource(\"file1\");\ncheck if time($time), $time <= 2018-12-20T00:00:00Z;\n" + "code": "check if resource(\"file1\");\ncheck if time($time), $time <= 2018-12-20T00:00:00Z;\n", + "version": 3 } ], "validations": { @@ -585,7 +606,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\n" + "code": "right(\"file1\", \"read\");\n", + "version": 3 }, { "symbols": [ @@ -593,7 +615,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file2\", \"read\");\n" + "code": "right(\"file2\", \"read\");\n", + "version": 3 } ], "validations": { @@ -676,7 +699,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\n" + "code": "right(\"file1\", \"read\");\n", + "version": 3 } ], "validations": { @@ -750,7 +774,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource(\"file1\");\n" + "code": "check if resource(\"file1\");\n", + "version": 3 } ], "validations": { @@ -852,7 +877,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\n", + "version": 3 }, { "symbols": [ @@ -862,7 +888,8 @@ ], "public_keys": [], "external_key": null, - "code": "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z;\nvalid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1);\ncheck if valid_date($0), resource($0);\n" + "code": "valid_date(\"file1\") <- time($0), resource(\"file1\"), $0 <= 2030-12-31T12:59:59Z;\nvalid_date($1) <- time($0), resource($1), $0 <= 1999-12-31T12:59:59Z, !{\"file1\"}.contains($1);\ncheck if valid_date($0), resource($0);\n", + "version": 3 } ], "validations": { @@ -1009,7 +1036,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), $0.matches(\"file[0-9]+.txt\");\n" + "code": "check if resource($0), $0.matches(\"file[0-9]+.txt\");\n", + "version": 3 } ], "validations": { @@ -1109,7 +1137,8 @@ ], "public_keys": [], "external_key": null, - "code": "must_be_present(\"hello\");\n" + "code": "must_be_present(\"hello\");\n", + "version": 3 } ], "validations": { @@ -1158,7 +1187,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource(\"hello\");\n" + "code": "check if resource(\"hello\");\n", + "version": 3 }, { "symbols": [ @@ -1166,7 +1196,8 @@ ], "public_keys": [], "external_key": null, - "code": "query(\"test\");\n" + "code": "query(\"test\");\n", + "version": 3 } ], "validations": { @@ -1245,7 +1276,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if true;\ncheck if !false;\ncheck if true === true;\ncheck if false === false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 === 3;\ncheck if 1 + 2 * 3 - 4 / 2 === 5;\ncheck if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" === \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" === \"abcD12\";\ncheck if \"abcD12\".length() === 6;\ncheck if \"é\".length() === 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z;\ncheck if hex:12ab === hex:12ab;\ncheck if {1, 2}.contains(2);\ncheck if {2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z}.contains(2020-12-04T09:46:41Z);\ncheck if {false, true}.contains(true);\ncheck if {\"abc\", \"def\"}.contains(\"abc\");\ncheck if {hex:12ab, hex:34de}.contains(hex:34de);\ncheck if {1, 2}.contains({2});\ncheck if {1, 2} === {1, 2};\ncheck if {1, 2}.intersection({2, 3}) === {2};\ncheck if {1, 2}.union({2, 3}) === {1, 2, 3};\ncheck if {1, 2, 3}.intersection({1, 2}).contains(1);\ncheck if {1, 2, 3}.intersection({1, 2}).length() === 2;\n" + "code": "check if true;\ncheck if !false;\ncheck if true === true;\ncheck if false === false;\ncheck if 1 < 2;\ncheck if 2 > 1;\ncheck if 1 <= 2;\ncheck if 1 <= 1;\ncheck if 2 >= 1;\ncheck if 2 >= 2;\ncheck if 3 === 3;\ncheck if 1 + 2 * 3 - 4 / 2 === 5;\ncheck if \"hello world\".starts_with(\"hello\"), \"hello world\".ends_with(\"world\");\ncheck if \"aaabde\".matches(\"a*c?.e\");\ncheck if \"aaabde\".contains(\"abd\");\ncheck if \"aaabde\" === \"aaa\" + \"b\" + \"de\";\ncheck if \"abcD12\" === \"abcD12\";\ncheck if \"abcD12\".length() === 6;\ncheck if \"é\".length() === 2;\ncheck if 2019-12-04T09:46:41Z < 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z > 2019-12-04T09:46:41Z;\ncheck if 2019-12-04T09:46:41Z <= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2019-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z >= 2020-12-04T09:46:41Z;\ncheck if 2020-12-04T09:46:41Z === 2020-12-04T09:46:41Z;\ncheck if hex:12ab === hex:12ab;\ncheck if {1, 2}.contains(2);\ncheck if {2019-12-04T09:46:41Z, 2020-12-04T09:46:41Z}.contains(2020-12-04T09:46:41Z);\ncheck if {false, true}.contains(true);\ncheck if {\"abc\", \"def\"}.contains(\"abc\");\ncheck if {hex:12ab, hex:34de}.contains(hex:34de);\ncheck if {1, 2}.contains({2});\ncheck if {1, 2} === {1, 2};\ncheck if {1, 2}.intersection({2, 3}) === {2};\ncheck if {1, 2}.union({2, 3}) === {1, 2, 3};\ncheck if {1, 2, 3}.intersection({1, 2}).contains(1);\ncheck if {1, 2, 3}.intersection({1, 2}).length() === 2;\n", + "version": 3 } ], "validations": { @@ -1320,7 +1352,8 @@ "symbols": [], "public_keys": [], "external_key": null, - "code": "check if operation(\"read\");\n" + "code": "check if operation(\"read\");\n", + "version": 3 }, { "symbols": [ @@ -1330,7 +1363,8 @@ ], "public_keys": [], "external_key": null, - "code": "operation($unbound, \"read\") <- operation($any1, $any2);\n" + "code": "operation($unbound, \"read\") <- operation($any1, $any2);\n", + "version": 3 } ], "validations": { @@ -1362,7 +1396,8 @@ "symbols": [], "public_keys": [], "external_key": null, - "code": "check if operation(\"read\");\n" + "code": "check if operation(\"read\");\n", + "version": 3 }, { "symbols": [ @@ -1370,7 +1405,8 @@ ], "public_keys": [], "external_key": null, - "code": "operation(\"read\") <- operation($any);\n" + "code": "operation(\"read\") <- operation($any);\n", + "version": 3 } ], "validations": { @@ -1454,7 +1490,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -1462,7 +1499,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { @@ -1524,7 +1562,8 @@ ], "public_keys": [], "external_key": null, - "code": "ns::fact_123(\"hello é\t😁\");\n" + "code": "ns::fact_123(\"hello é\t😁\");\n", + "version": 3 } ], "validations": { @@ -1571,7 +1610,8 @@ "symbols": [], "public_keys": [], "external_key": null, - "code": "read(0);\nwrite(1);\nresource(2);\noperation(3);\nright(4);\ntime(5);\nrole(6);\nowner(7);\ntenant(8);\nnamespace(9);\nuser(10);\nteam(11);\nservice(12);\nadmin(13);\nemail(14);\ngroup(15);\nmember(16);\nip_address(17);\nclient(18);\nclient_ip(19);\ndomain(20);\npath(21);\nversion(22);\ncluster(23);\nnode(24);\nhostname(25);\nnonce(26);\nquery(27);\n" + "code": "read(0);\nwrite(1);\nresource(2);\noperation(3);\nright(4);\ntime(5);\nrole(6);\nowner(7);\ntenant(8);\nnamespace(9);\nuser(10);\nteam(11);\nservice(12);\nadmin(13);\nemail(14);\ngroup(15);\nmember(16);\nip_address(17);\nclient(18);\nclient_ip(19);\ndomain(20);\npath(21);\nversion(22);\ncluster(23);\nnode(24);\nhostname(25);\nnonce(26);\nquery(27);\n", + "version": 3 } ], "validations": { @@ -1647,7 +1687,8 @@ ], "public_keys": [], "external_key": null, - "code": "authority_fact(1);\n" + "code": "authority_fact(1);\n", + "version": 3 }, { "symbols": [ @@ -1655,7 +1696,8 @@ ], "public_keys": [], "external_key": null, - "code": "block1_fact(1);\n" + "code": "block1_fact(1);\n", + "version": 3 }, { "symbols": [ @@ -1663,7 +1705,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if authority_fact($var);\ncheck if block1_fact($var);\n" + "code": "check if authority_fact($var);\ncheck if block1_fact($var);\n", + "version": 3 } ], "validations": { @@ -1740,13 +1783,15 @@ "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" ], "external_key": null, - "code": "right(\"read\");\ncheck if group(\"admin\") trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" + "code": "right(\"read\");\ncheck if group(\"admin\") trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n", + "version": 4 }, { "symbols": [], "public_keys": [], "external_key": "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189", - "code": "group(\"admin\");\ncheck if right(\"read\");\n" + "code": "group(\"admin\");\ncheck if right(\"read\");\n", + "version": 5 } ], "validations": { @@ -1814,7 +1859,8 @@ ], "public_keys": [], "external_key": null, - "code": "allowed_operations({\"A\", \"B\"});\ncheck all operation($op), allowed_operations($allowed), $allowed.contains($op);\n" + "code": "allowed_operations({\"A\", \"B\"});\ncheck all operation($op), allowed_operations($allowed), $allowed.contains($op);\n", + "version": 4 } ], "validations": { @@ -1931,7 +1977,8 @@ "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" ], "external_key": null, - "code": "query(0);\ncheck if true trusting previous, ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" + "code": "query(0);\ncheck if true trusting previous, ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n", + "version": 4 }, { "symbols": [], @@ -1940,7 +1987,8 @@ "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" ], "external_key": "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189", - "code": "query(1);\nquery(1, 2) <- query(1), query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" + "code": "query(1);\nquery(1, 2) <- query(1), query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n", + "version": 5 }, { "symbols": [], @@ -1949,7 +1997,8 @@ "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" ], "external_key": "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", - "code": "query(2);\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" + "code": "query(2);\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n", + "version": 5 }, { "symbols": [], @@ -1958,7 +2007,8 @@ "ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189" ], "external_key": "ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463", - "code": "query(3);\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n" + "code": "query(3);\ncheck if query(2), query(3) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(1) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189;\n", + "version": 5 }, { "symbols": [], @@ -1967,7 +2017,8 @@ "ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136" ], "external_key": null, - "code": "query(4);\ncheck if query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(4) trusting ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136;\n" + "code": "query(4);\ncheck if query(2) trusting ed25519/a060270db7e9c9f06e8f9cc33a64e99f6596af12cb01c4b638df8afc7b642463;\ncheck if query(4) trusting ed25519/f98da8c1cf907856431bfc3dc87531e0eaadba90f919edc232405b85877ef136;\n", + "version": 4 } ], "validations": { @@ -2103,7 +2154,8 @@ "symbols": [], "public_keys": [], "external_key": null, - "code": "check if 10000000000 * 10000000000 !== 0;\ncheck if 9223372036854775807 + 1 !== 0;\ncheck if -9223372036854775808 - 1 !== 0;\n" + "code": "check if 10000000000 * 10000000000 !== 0;\ncheck if 9223372036854775807 + 1 !== 0;\ncheck if -9223372036854775808 - 1 !== 0;\n", + "version": 4 } ], "validations": { @@ -2148,7 +2200,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if 1 !== 3;\ncheck if 1 | 2 ^ 3 === 0;\ncheck if \"abcD12x\" !== \"abcD12\";\ncheck if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z;\ncheck if hex:12abcd !== hex:12ab;\ncheck if {1, 4} !== {1, 2};\n" + "code": "check if 1 !== 3;\ncheck if 1 | 2 ^ 3 === 0;\ncheck if \"abcD12x\" !== \"abcD12\";\ncheck if 2022-12-04T09:46:41Z !== 2020-12-04T09:46:41Z;\ncheck if hex:12abcd !== hex:12ab;\ncheck if {1, 4} !== {1, 2};\n", + "version": 4 } ], "validations": { @@ -2193,7 +2246,8 @@ ], "public_keys": [], "external_key": null, - "code": "reject if test($test), $test;\n" + "code": "reject if test($test), $test;\n", + "version": 6 } ], "validations": { @@ -2293,7 +2347,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if fact(null, $value), $value == null;\nreject if fact(null, $value), $value != null;\n" + "code": "check if fact(null, $value), $value == null;\nreject if fact(null, $value), $value != null;\n", + "version": 6 } ], "validations": { @@ -2521,7 +2576,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if true == true;\ncheck if false == false;\ncheck if false != true;\ncheck if 1 != true;\ncheck if 1 == 1;\ncheck if 1 != 3;\ncheck if 1 != true;\ncheck if \"abcD12\" == \"abcD12\";\ncheck if \"abcD12x\" != \"abcD12\";\ncheck if \"abcD12x\" != true;\ncheck if 2022-12-04T09:46:41Z == 2022-12-04T09:46:41Z;\ncheck if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z;\ncheck if 2022-12-04T09:46:41Z != true;\ncheck if hex:12abcd == hex:12abcd;\ncheck if hex:12abcd != hex:12ab;\ncheck if hex:12abcd != true;\ncheck if {1, 2} == {1, 2};\ncheck if {1, 4} != {1, 2};\ncheck if {1, 4} != true;\ncheck if fact(1, $value), 1 == $value;\ncheck if fact2(1, $value), 1 != $value;\n" + "code": "check if true == true;\ncheck if false == false;\ncheck if false != true;\ncheck if 1 != true;\ncheck if 1 == 1;\ncheck if 1 != 3;\ncheck if 1 != true;\ncheck if \"abcD12\" == \"abcD12\";\ncheck if \"abcD12x\" != \"abcD12\";\ncheck if \"abcD12x\" != true;\ncheck if 2022-12-04T09:46:41Z == 2022-12-04T09:46:41Z;\ncheck if 2022-12-04T09:46:41Z != 2020-12-04T09:46:41Z;\ncheck if 2022-12-04T09:46:41Z != true;\ncheck if hex:12abcd == hex:12abcd;\ncheck if hex:12abcd != hex:12ab;\ncheck if hex:12abcd != true;\ncheck if {1, 2} == {1, 2};\ncheck if {1, 4} != {1, 2};\ncheck if {1, 4} != true;\ncheck if fact(1, $value), 1 == $value;\ncheck if fact2(1, $value), 1 != $value;\n", + "version": 6 } ], "validations": { @@ -2683,7 +2739,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if !(false && \"x\".intersection(\"x\"));\ncheck if true || \"x\".intersection(\"x\");\ncheck if {1, 2, 3}.all($p -> $p > 0);\ncheck if !{1, 2, 3}.all($p -> $p == 2);\ncheck if {1, 2, 3}.any($p -> $p > 2);\ncheck if !{1, 2, 3}.any($p -> $p > 3);\ncheck if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q));\n" + "code": "check if !false && true;\ncheck if false || true;\ncheck if (true || false) && true;\ncheck if !(false && \"x\".intersection(\"x\"));\ncheck if true || \"x\".intersection(\"x\");\ncheck if {1, 2, 3}.all($p -> $p > 0);\ncheck if !{1, 2, 3}.all($p -> $p == 2);\ncheck if {1, 2, 3}.any($p -> $p > 2);\ncheck if !{1, 2, 3}.any($p -> $p > 3);\ncheck if {1, 2, 3}.any($p -> $p > 1 && {3, 4, 5}.any($q -> $p == $q));\n", + "version": 6 } ], "validations": { @@ -2778,7 +2835,8 @@ ], "public_keys": [], "external_key": null, - "code": "integer(1);\nstring(\"test\");\ndate(2023-12-28T00:00:00Z);\nbytes(hex:aa);\nbool(true);\nset({false, true});\nnull(null);\narray([1, 2, 3]);\nmap({\"a\": true});\ncheck if 1.type() == \"integer\";\ncheck if integer($t), $t.type() == \"integer\";\ncheck if \"test\".type() == \"string\";\ncheck if string($t), $t.type() == \"string\";\ncheck if (2023-12-28T00:00:00Z).type() == \"date\";\ncheck if date($t), $t.type() == \"date\";\ncheck if hex:aa.type() == \"bytes\";\ncheck if bytes($t), $t.type() == \"bytes\";\ncheck if true.type() == \"bool\";\ncheck if bool($t), $t.type() == \"bool\";\ncheck if {false, true}.type() == \"set\";\ncheck if set($t), $t.type() == \"set\";\ncheck if null.type() == \"null\";\ncheck if null($t), $t.type() == \"null\";\ncheck if array($t), $t.type() == \"array\";\ncheck if map($t), $t.type() == \"map\";\n" + "code": "integer(1);\nstring(\"test\");\ndate(2023-12-28T00:00:00Z);\nbytes(hex:aa);\nbool(true);\nset({false, true});\nnull(null);\narray([1, 2, 3]);\nmap({\"a\": true});\ncheck if 1.type() == \"integer\";\ncheck if integer($t), $t.type() == \"integer\";\ncheck if \"test\".type() == \"string\";\ncheck if string($t), $t.type() == \"string\";\ncheck if (2023-12-28T00:00:00Z).type() == \"date\";\ncheck if date($t), $t.type() == \"date\";\ncheck if hex:aa.type() == \"bytes\";\ncheck if bytes($t), $t.type() == \"bytes\";\ncheck if true.type() == \"bool\";\ncheck if bool($t), $t.type() == \"bool\";\ncheck if {false, true}.type() == \"set\";\ncheck if set($t), $t.type() == \"set\";\ncheck if null.type() == \"null\";\ncheck if null($t), $t.type() == \"null\";\ncheck if array($t), $t.type() == \"array\";\ncheck if map($t), $t.type() == \"map\";\n", + "version": 6 } ], "validations": { @@ -2858,7 +2916,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if [1, 2, 1].length() == 3;\ncheck if [\"a\", \"b\"] != true;\ncheck if [\"a\", \"b\"] != [1, 2, 3];\ncheck if [\"a\", \"b\"] == [\"a\", \"b\"];\ncheck if [\"a\", \"b\"] === [\"a\", \"b\"];\ncheck if [\"a\", \"b\"] !== [\"a\", \"c\"];\ncheck if [\"a\", \"b\", \"c\"].contains(\"c\");\ncheck if [1, 2, 3].starts_with([1, 2]);\ncheck if [4, 5, 6].ends_with([6]);\ncheck if [1, 2, \"a\"].get(2) == \"a\";\ncheck if [1, 2].get(3) == null;\ncheck if [1, 2, 3].all($p -> $p > 0);\ncheck if [1, 2, 3].any($p -> $p > 2);\ncheck if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.length() == 4;\ncheck if {1: \"a\", 2: \"b\"} != true;\ncheck if {1: \"a\", 2: \"b\"} != {\"a\": 1, \"b\": 2};\ncheck if {1: \"a\", 2: \"b\"} == {1: \"a\", 2: \"b\"};\ncheck if {1: \"a\", 2: \"b\"} !== {\"a\": 1, \"b\": 2};\ncheck if {1: \"a\", 2: \"b\"} === {1: \"a\", 2: \"b\"};\ncheck if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.contains(\"d\");\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"a\") == 1;\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(1) == \"A\";\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"c\") == null;\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(2) == null;\ncheck if {\"a\": 1, \"b\": 2}.all($kv -> $kv.get(0) != \"c\" && $kv.get(1) < 3);\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.any($kv -> $kv.get(0) == 1 && $kv.get(1) == \"A\");\ncheck if {\"user\": {\"id\": 1, \"roles\": [\"admin\"]}}.get(\"user\").get(\"roles\").contains(\"admin\");\n" + "code": "check if [1, 2, 1].length() == 3;\ncheck if [\"a\", \"b\"] != true;\ncheck if [\"a\", \"b\"] != [1, 2, 3];\ncheck if [\"a\", \"b\"] == [\"a\", \"b\"];\ncheck if [\"a\", \"b\"] === [\"a\", \"b\"];\ncheck if [\"a\", \"b\"] !== [\"a\", \"c\"];\ncheck if [\"a\", \"b\", \"c\"].contains(\"c\");\ncheck if [1, 2, 3].starts_with([1, 2]);\ncheck if [4, 5, 6].ends_with([6]);\ncheck if [1, 2, \"a\"].get(2) == \"a\";\ncheck if [1, 2].get(3) == null;\ncheck if [1, 2, 3].all($p -> $p > 0);\ncheck if [1, 2, 3].any($p -> $p > 2);\ncheck if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.length() == 4;\ncheck if {1: \"a\", 2: \"b\"} != true;\ncheck if {1: \"a\", 2: \"b\"} != {\"a\": 1, \"b\": 2};\ncheck if {1: \"a\", 2: \"b\"} == {1: \"a\", 2: \"b\"};\ncheck if {1: \"a\", 2: \"b\"} !== {\"a\": 1, \"b\": 2};\ncheck if {1: \"a\", 2: \"b\"} === {1: \"a\", 2: \"b\"};\ncheck if {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}.contains(\"d\");\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"a\") == 1;\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(1) == \"A\";\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(\"c\") == null;\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.get(2) == null;\ncheck if {\"a\": 1, \"b\": 2}.all($kv -> $kv.get(0) != \"c\" && $kv.get(1) < 3);\ncheck if {1: \"A\", \"a\": 1, \"b\": 2}.any($kv -> $kv.get(0) == 1 && $kv.get(1) == \"A\");\ncheck if {\"user\": {\"id\": 1, \"roles\": [\"admin\"]}}.get(\"user\").get(\"roles\").contains(\"admin\");\n", + "version": 6 } ], "validations": { @@ -2926,7 +2985,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if true.extern::test(), \"a\".extern::test(\"a\") == \"equal strings\";\n" + "code": "check if true.extern::test(), \"a\".extern::test(\"a\") == \"equal strings\";\n", + "version": 6 } ], "validations": { @@ -2967,7 +3027,8 @@ ], "public_keys": [], "external_key": null, - "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n" + "code": "right(\"file1\", \"read\");\nright(\"file2\", \"read\");\nright(\"file1\", \"write\");\n", + "version": 3 }, { "symbols": [ @@ -2975,7 +3036,8 @@ ], "public_keys": [], "external_key": null, - "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n" + "code": "check if resource($0), operation(\"read\"), right($0, \"read\");\n", + "version": 3 } ], "validations": { diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 6dac4c35..b0aa3d40 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -242,6 +242,11 @@ impl Biscuit { }) } + /// gets the datalog version for a given block + pub fn block_version(&self, index: usize) -> Result { + self.block(index).map(|block| block.version) + } + /// creates a new token, using a provided CSPRNG /// /// the public part of the root keypair must be used for verification @@ -1572,4 +1577,30 @@ mod tests { let _ = Biscuit::from(&serialized, root.public()).unwrap(); } + + #[test] + fn verified_unverified_consistency() { + let mut rng: StdRng = SeedableRng::seed_from_u64(0); + let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let mut builder = Biscuit::builder(); + + builder.add_fact("right(\"file1\", \"read\")").unwrap(); + builder.add_fact("right(\"file2\", \"read\")").unwrap(); + builder.add_fact("right(\"file1\", \"write\")").unwrap(); + + let biscuit1 = builder + .build_with_rng(&root, default_symbol_table(), &mut rng) + .unwrap(); + + println!("biscuit1 (authority): {}", biscuit1); + + let serialized = biscuit1.to_vec().unwrap(); + + let parsed = UnverifiedBiscuit::from(serialized).unwrap(); + + for i in 0..parsed.block_count() { + assert_eq!(parsed.print_block_source(i), biscuit1.print_block_source(i)); + assert_eq!(parsed.block_version(i), biscuit1.block_version(i)); + } + } } diff --git a/biscuit-auth/src/token/unverified.rs b/biscuit-auth/src/token/unverified.rs index b3970904..20d07bae 100644 --- a/biscuit-auth/src/token/unverified.rs +++ b/biscuit-auth/src/token/unverified.rs @@ -248,6 +248,11 @@ impl UnverifiedBiscuit { }) } + /// gets the datalog version for a given block + pub fn block_version(&self, index: usize) -> Result { + self.block(index).map(|block| block.version) + } + pub(crate) fn block(&self, index: usize) -> Result { let mut block = if index == 0 { proto_block_to_token_block(