diff --git a/cedar-drt/fuzz/fuzz_targets/protobuf-roundtrip.rs b/cedar-drt/fuzz/fuzz_targets/protobuf-roundtrip.rs index 85d24dc04..69ed748f1 100644 --- a/cedar-drt/fuzz/fuzz_targets/protobuf-roundtrip.rs +++ b/cedar-drt/fuzz/fuzz_targets/protobuf-roundtrip.rs @@ -22,7 +22,7 @@ use serde::Serialize; use crate::arbitrary::Arbitrary; use crate::arbitrary::Unstructured; -use cedar_drt::{AuthorizationRequestMsg, OwnedAuthorizationRequestMsg}; +use cedar_drt::{AuthorizationRequest, OwnedAuthorizationRequest}; use cedar_drt_inner::{fuzz_target, schemas::Equiv}; use cedar_policy::proto; use cedar_policy_core::{ @@ -97,7 +97,7 @@ fuzz_target!(|input: FuzzTargetInput| { let s_policy: ast::StaticPolicy = input.policy.into(); let mut policies: ast::PolicySet = ast::PolicySet::new(); policies.add(s_policy.into()).expect("Failed to add policy"); - roundtrip_authz_request_msg(AuthorizationRequestMsg { + roundtrip_authz_request_msg(AuthorizationRequest { request: &input.request.into(), policies: &policies, entities: &input.entities, @@ -105,19 +105,19 @@ fuzz_target!(|input: FuzzTargetInput| { roundtrip_schema(input.schema); }); -fn roundtrip_authz_request_msg(auth_request: AuthorizationRequestMsg) { +fn roundtrip_authz_request_msg(auth_request: AuthorizationRequest) { // AST -> Protobuf - let auth_request_proto = cedar_drt::proto::AuthorizationRequestMsg::from(&auth_request); + let auth_request_proto = cedar_drt::proto::AuthorizationRequest::from(&auth_request); // Protobuf -> Bytes let buf = auth_request_proto.encode_to_vec(); // Bytes -> Protobuf - let roundtripped_proto = cedar_drt::proto::AuthorizationRequestMsg::decode(&buf[..]) - .expect("Failed to deserialize AuthorizationRequestMsg from proto"); + let roundtripped_proto = cedar_drt::proto::AuthorizationRequest::decode(&buf[..]) + .expect("Failed to deserialize AuthorizationRequest from proto"); // Protobuf -> AST - let roundtripped = OwnedAuthorizationRequestMsg::from(roundtripped_proto); + let roundtripped = OwnedAuthorizationRequest::from(roundtripped_proto); // Checking request equality (ignores loc field) assert_eq!( diff --git a/cedar-drt/fuzz/src/lib.rs b/cedar-drt/fuzz/src/lib.rs index db511d084..be5c7c895 100644 --- a/cedar-drt/fuzz/src/lib.rs +++ b/cedar-drt/fuzz/src/lib.rs @@ -315,10 +315,9 @@ pub fn run_req_val_test( }); info!("{}{}", RUST_REQ_VALIDATION_MSG, rust_auth_dur.as_nanos()); - let definitional_res = custom_impl.validate_request(&schema, &request); - match definitional_res { - TestResult::Failure(_) => { - panic!("request validation test: failed to parse"); + match custom_impl.validate_request(&schema, &request) { + TestResult::Failure(e) => { + panic!("failed to execute request validation: {e}"); } TestResult::Success(definitional_res) => { if rust_res.is_ok() { @@ -354,10 +353,9 @@ pub fn run_ent_val_test( ) }); info!("{}{}", RUST_ENT_VALIDATION_MSG, rust_auth_dur.as_nanos()); - let definitional_res = custom_impl.validate_entities(&schema, &entities); - match definitional_res { - TestResult::Failure(_) => { - panic!("entity validation test: failed to parse"); + match custom_impl.validate_entities(&schema, &entities) { + TestResult::Failure(e) => { + panic!("failed to execute entity validation: {e}"); } TestResult::Success(definitional_res) => { if rust_res.is_ok() { diff --git a/cedar-drt/protobuf_schema/Messages.proto b/cedar-drt/protobuf_schema/Messages.proto index 124dbf507..8a69ff1ed 100644 --- a/cedar-drt/protobuf_schema/Messages.proto +++ b/cedar-drt/protobuf_schema/Messages.proto @@ -3,14 +3,31 @@ package cedar_drt; import "core.proto"; import "validator.proto"; -message AuthorizationRequestMsg { +message AuthorizationRequest { cedar_policy_core.Request request = 1; cedar_policy_core.PolicySet policies = 2; cedar_policy_core.Entities entities = 3; } -message ValidationRequestMsg { +message ValidationRequest { cedar_policy_validator.Schema schema = 1; cedar_policy_core.PolicySet policies = 2; cedar_policy_validator.ValidationMode mode = 3; } + +message EvaluationRequest { + cedar_policy_core.Expr expr = 1; + cedar_policy_core.Request request = 2; + cedar_policy_core.Entities entities = 3; + cedar_policy_core.Expr expected = 4; +} + +message EntityValidationRequest { + cedar_policy_validator.Schema schema = 1; + cedar_policy_core.Entities entities = 2; +} + +message RequestValidationRequest { + cedar_policy_validator.Schema schema = 1; + cedar_policy_core.Request request = 2; +} diff --git a/cedar-drt/src/definitional_request_types.rs b/cedar-drt/src/definitional_request_types.rs index a821ff802..d37c05e65 100644 --- a/cedar-drt/src/definitional_request_types.rs +++ b/cedar-drt/src/definitional_request_types.rs @@ -25,15 +25,15 @@ pub mod proto { include!(concat!(env!("OUT_DIR"), "/cedar_drt.rs")); } -#[derive(Clone, Debug, Serialize)] -pub struct AuthorizationRequestMsg<'a> { +#[derive(Clone, Debug)] +pub struct AuthorizationRequest<'a> { pub request: &'a ast::Request, pub policies: &'a ast::PolicySet, pub entities: &'a Entities, } -impl From<&AuthorizationRequestMsg<'_>> for proto::AuthorizationRequestMsg { - fn from(v: &AuthorizationRequestMsg<'_>) -> Self { +impl From<&AuthorizationRequest<'_>> for proto::AuthorizationRequest { + fn from(v: &AuthorizationRequest<'_>) -> Self { Self { request: Some(cedar_policy::proto::models::Request::from(v.request)), policies: Some(cedar_policy::proto::models::PolicySet::from(v.policies)), @@ -42,17 +42,17 @@ impl From<&AuthorizationRequestMsg<'_>> for proto::AuthorizationRequestMsg { } } -// Converting `AuthorizationRequestMsg` from proto to non-proto structures is +// Converting `AuthorizationRequest` from proto to non-proto structures is // only required for some roundtrip tests #[derive(Clone, Debug)] -pub struct OwnedAuthorizationRequestMsg { +pub struct OwnedAuthorizationRequest { pub request: ast::Request, pub policies: ast::PolicySet, pub entities: Entities, } -impl From for OwnedAuthorizationRequestMsg { - fn from(v: proto::AuthorizationRequestMsg) -> Self { +impl From for OwnedAuthorizationRequest { + fn from(v: proto::AuthorizationRequest) -> Self { Self { request: ast::Request::from(&v.request.unwrap_or_default()), policies: ast::PolicySet::try_from(&v.policies.unwrap_or_default()) @@ -62,15 +62,15 @@ impl From for OwnedAuthorizationRequestMsg { } } -#[derive(Clone, Debug, Serialize)] -pub struct ValidationRequestMsg<'a> { +#[derive(Clone, Debug)] +pub struct ValidationRequest<'a> { pub schema: &'a ValidatorSchema, pub policies: &'a ast::PolicySet, pub mode: ValidationMode, } -impl From<&ValidationRequestMsg<'_>> for proto::ValidationRequestMsg { - fn from(v: &ValidationRequestMsg<'_>) -> Self { +impl From<&ValidationRequest<'_>> for proto::ValidationRequest { + fn from(v: &ValidationRequest<'_>) -> Self { Self { schema: Some(cedar_policy::proto::models::Schema::from(v.schema)), policies: Some(cedar_policy::proto::models::PolicySet::from(v.policies)), @@ -79,14 +79,7 @@ impl From<&ValidationRequestMsg<'_>> for proto::ValidationRequestMsg { } } -#[derive(Debug, Serialize)] -pub struct AuthorizationRequest<'a> { - pub request: &'a ast::Request, - pub policies: &'a ast::PolicySet, - pub entities: &'a Entities, -} - -#[derive(Debug, Serialize)] +#[derive(Clone, Debug)] pub struct EvaluationRequest<'a> { pub request: &'a ast::Request, pub entities: &'a Entities, @@ -94,7 +87,18 @@ pub struct EvaluationRequest<'a> { pub expected: Option<&'a ast::Expr>, } -#[derive(Debug, Serialize)] +impl From<&EvaluationRequest<'_>> for proto::EvaluationRequest { + fn from(v: &EvaluationRequest<'_>) -> Self { + Self { + expr: Some(cedar_policy::proto::models::Expr::from(v.expr)), + request: Some(cedar_policy::proto::models::Request::from(v.request)), + entities: Some(cedar_policy::proto::models::Entities::from(v.entities)), + expected: v.expected.map(cedar_policy::proto::models::Expr::from), + } + } +} + +#[derive(Debug, Serialize, Clone)] pub struct PartialEvaluationRequest<'a> { pub request: &'a ast::Request, pub entities: &'a Entities, @@ -102,28 +106,39 @@ pub struct PartialEvaluationRequest<'a> { pub expected: Option, } -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, Clone)] pub struct PartialAuthorizationRequest<'a> { pub request: &'a ast::Request, pub entities: &'a Entities, pub policies: &'a ast::PolicySet, } -#[derive(Debug, Serialize)] -pub struct ValidationRequest<'a> { - pub schema: &'a ValidatorSchema, - pub policies: &'a ast::PolicySet, - pub mode: ValidationMode, -} - -#[derive(Debug, Serialize)] +#[derive(Debug, Clone)] pub struct RequestValidationRequest<'a> { pub schema: &'a ValidatorSchema, pub request: &'a ast::Request, } -#[derive(Debug, Serialize)] +impl From<&RequestValidationRequest<'_>> for proto::RequestValidationRequest { + fn from(v: &RequestValidationRequest<'_>) -> Self { + Self { + schema: Some(cedar_policy::proto::models::Schema::from(v.schema)), + request: Some(cedar_policy::proto::models::Request::from(v.request)), + } + } +} + +#[derive(Debug, Clone)] pub struct EntityValidationRequest<'a> { pub schema: &'a ValidatorSchema, pub entities: &'a Entities, } + +impl From<&EntityValidationRequest<'_>> for proto::EntityValidationRequest { + fn from(v: &EntityValidationRequest<'_>) -> Self { + Self { + schema: Some(cedar_policy::proto::models::Schema::from(v.schema)), + entities: Some(cedar_policy::proto::models::Entities::from(v.entities)), + } + } +} diff --git a/cedar-drt/src/lean_impl.rs b/cedar-drt/src/lean_impl.rs index f03936d70..c5f58f20e 100644 --- a/cedar-drt/src/lean_impl.rs +++ b/cedar-drt/src/lean_impl.rs @@ -227,12 +227,12 @@ impl LeanDefinitionalEngine { policies: &ast::PolicySet, entities: &Entities, ) -> TestResult { - let auth_request = AuthorizationRequestMsg { + let auth_request = AuthorizationRequest { request, policies, entities, }; - let auth_request_proto = proto::AuthorizationRequestMsg::from(&auth_request); + let auth_request_proto = proto::AuthorizationRequest::from(&auth_request); let buf = auth_request_proto.encode_to_vec(); let req = buf_to_lean_obj(&buf); // Lean will decrement the reference count when we pass this object: https://github.com/leanprover/lean4/blob/master/src/include/lean/lean.h @@ -336,16 +336,16 @@ impl LeanDefinitionalEngine { expected: Option, ) -> TestResult { let expected_as_expr: Option = expected.map(|v| v.into()); - let request: String = serde_json::to_string(&EvaluationRequest { + let req = EvaluationRequest { request, entities, expr, expected: expected_as_expr.as_ref(), - }) - .expect("failed to serialize request, expression, or entities"); - let cstring = CString::new(request).expect("`CString::new` failed"); + }; + let req_proto = proto::EvaluationRequest::from(&req); + let buf = req_proto.encode_to_vec(); + let req = buf_to_lean_obj(&buf); // Lean will decrement the reference count when we pass this object: https://github.com/leanprover/lean4/blob/master/src/include/lean/lean.h - let req = unsafe { lean_mk_string(cstring.as_ptr() as *const u8) }; let response = unsafe { evaluateDRT(req) }; // req can no longer be assumed to exist let response_string = lean_obj_p_to_rust_string(response); @@ -380,12 +380,12 @@ impl LeanDefinitionalEngine { schema: &ValidatorSchema, policies: &ast::PolicySet, ) -> TestResult { - let val_request = ValidationRequestMsg { + let val_request = ValidationRequest { schema, policies, mode: cedar_policy_validator::ValidationMode::default(), }; - let val_request_proto = proto::ValidationRequestMsg::from(&val_request); + let val_request_proto = proto::ValidationRequest::from(&val_request); let buf = val_request_proto.encode_to_vec(); let req = buf_to_lean_obj(&buf); // Lean will decrement the reference count when we pass this object: https://github.com/leanprover/lean4/blob/master/src/include/lean/lean.h @@ -400,11 +400,13 @@ impl LeanDefinitionalEngine { schema: &ValidatorSchema, request: &ast::Request, ) -> TestResult { - let request: String = serde_json::to_string(&RequestValidationRequest { schema, request }) - .expect("failed to serialize request"); - let cstring = CString::new(request).expect("CString::new failed"); - let req = unsafe { lean_mk_string(cstring.as_ptr() as *const u8) }; + let req = RequestValidationRequest { schema, request }; + let req_proto = proto::RequestValidationRequest::from(&req); + let buf = req_proto.encode_to_vec(); + let req = buf_to_lean_obj(&buf); + // Lean will decrement the reference count when we pass this object: https://github.com/leanprover/lean4/blob/master/src/include/lean/lean.h let response = unsafe { validateRequestDRT(req) }; + // req can no longer be assumed to exist let response_string = lean_obj_p_to_rust_string(response); Self::deserialize_validation_response(response_string) } @@ -414,11 +416,13 @@ impl LeanDefinitionalEngine { schema: &ValidatorSchema, entities: &Entities, ) -> TestResult { - let request: String = serde_json::to_string(&EntityValidationRequest { schema, entities }) - .expect("failed to serialize request"); - let cstring = CString::new(request).expect("CString::new failed"); - let req = unsafe { lean_mk_string(cstring.as_ptr() as *const u8) }; + let req = EntityValidationRequest { schema, entities }; + let req_proto = proto::EntityValidationRequest::from(&req); + let buf = req_proto.encode_to_vec(); + let req = buf_to_lean_obj(&buf); + // Lean will decrement the reference count when we pass this object: https://github.com/leanprover/lean4/blob/master/src/include/lean/lean.h let response = unsafe { validateEntitiesDRT(req) }; + // req can no longer be assumed to exist let response_string = lean_obj_p_to_rust_string(response); Self::deserialize_validation_response(response_string) } diff --git a/cedar-drt/tests/integration_tests.rs b/cedar-drt/tests/integration_tests.rs index cecbc8cd9..1516e2bba 100644 --- a/cedar-drt/tests/integration_tests.rs +++ b/cedar-drt/tests/integration_tests.rs @@ -104,8 +104,6 @@ fn protobuf_roundtrip() { let mut proto_serialize_durs: Vec = vec![]; let mut proto_serialize_sizes: Vec = vec![]; let mut proto_deserialize_durs: Vec = vec![]; - let mut json_serialize_durs: Vec = vec![]; - let mut json_serialize_sizes: Vec = vec![]; for test in tests { // Load test from JSON file @@ -126,15 +124,15 @@ fn protobuf_roundtrip() { for request in requests { // Construct Message - let request_msg = AuthorizationRequestMsg { + let request_msg = AuthorizationRequest { request: &request, policies: &policies, entities: &entities, }; // Perform a roundtrip serialize/de-serialize from protobuf and AST - let request_msg_proto = proto::AuthorizationRequestMsg::from(&request_msg); - let request_msg_rt = OwnedAuthorizationRequestMsg::from(request_msg_proto); + let request_msg_proto = proto::AuthorizationRequest::from(&request_msg); + let request_msg_rt = OwnedAuthorizationRequest::from(request_msg_proto); // Checking request equality (ignores loc field) assert_eq!( @@ -162,15 +160,13 @@ fn protobuf_roundtrip() { // Time protobuf serialization from AST -> bytes let (request_msg_proto, proto_serialize_dur): (Vec, Duration) = - time_function(|| { - proto::AuthorizationRequestMsg::from(&request_msg).encode_to_vec() - }); + time_function(|| proto::AuthorizationRequest::from(&request_msg).encode_to_vec()); // Time protobuf deserialization from bytes -> AST let (_request_msg_rt, proto_deserialize_dur) = time_function(|| { - OwnedAuthorizationRequestMsg::from( - proto::AuthorizationRequestMsg::decode(&request_msg_proto[..]) - .expect("Failed to deserialize AuthorizationRequestMsg proto"), + OwnedAuthorizationRequest::from( + proto::AuthorizationRequest::decode(&request_msg_proto[..]) + .expect("Failed to deserialize AuthorizationRequest proto"), ) }); @@ -182,20 +178,6 @@ fn protobuf_roundtrip() { as f64, ); proto_deserialize_durs.push(proto_deserialize_dur.as_micros() as f64); - - // Time JSON serialization to a string - let (request_json, json_serialize_dur) = time_function(|| { - serde_json::to_string(&AuthorizationRequest { - request: &request, - policies: &policies, - entities: &entities, - }) - .expect("Failed to seralize Authorization request") - }); - - // Log JSON serialization time and size of string - json_serialize_durs.push(json_serialize_dur.as_micros() as f64); - json_serialize_sizes.push(request_json.len() as f64); } } @@ -221,16 +203,4 @@ fn protobuf_roundtrip() { let std_proto_deserialize_dur = d_proto_deserialize_durs.std_dev().unwrap(); println!("Protobuf Mean Deserialization Time {mean_proto_deserialize_dur} micros"); println!("Protobuf Std Deserialization Time {std_proto_deserialize_dur} micros\n"); - - let d_json_serialize_durs = Data::new(json_serialize_durs); - let mean_json_serialize_dur = d_json_serialize_durs.mean().unwrap(); - let std_json_serialize_dur = d_json_serialize_durs.std_dev().unwrap(); - println!("JSON Mean Serialization Time {mean_json_serialize_dur} micros"); - println!("JSON Std Serialization Time {std_json_serialize_dur} micros\n"); - - let d_json_serialize_sizes = Data::new(json_serialize_sizes); - let mean_json_serialize_size = d_json_serialize_sizes.mean().unwrap(); - let std_json_serialize_size = d_json_serialize_sizes.std_dev().unwrap(); - println!("JSON Mean Serialization Size {mean_json_serialize_size} bytes"); - println!("JSON Std Serialization Size {std_json_serialize_size} bytes"); } diff --git a/cedar-lean/CedarProto.lean b/cedar-lean/CedarProto.lean index 807c2a652..b4eca3af7 100644 --- a/cedar-lean/CedarProto.lean +++ b/cedar-lean/CedarProto.lean @@ -22,12 +22,15 @@ import CedarProto.Entity import CedarProto.EntityDecl import CedarProto.EntityReference import CedarProto.EntityUID +import CedarProto.EntityValidationRequest +import CedarProto.EvaluationRequest import CedarProto.Expr import CedarProto.Name import CedarProto.Policy import CedarProto.PolicySet import CedarProto.PrincipalOrResourceConstraint import CedarProto.Request +import CedarProto.RequestValidationRequest import CedarProto.Schema import CedarProto.TemplateBody import CedarProto.Type diff --git a/cedar-lean/CedarProto/EntityValidationRequest.lean b/cedar-lean/CedarProto/EntityValidationRequest.lean new file mode 100644 index 000000000..332921076 --- /dev/null +++ b/cedar-lean/CedarProto/EntityValidationRequest.lean @@ -0,0 +1,51 @@ +/- + Copyright Cedar Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-/ + +import Cedar.Spec +import Protobuf.Message +import Protobuf.Structure + +-- Message Dependencies +import CedarProto.Schema +import CedarProto.Entities + + +open Proto + +namespace Cedar.Validation.Proto + +structure EntityValidationRequest where + schema : Validation.Schema + entities : Cedar.Spec.Entities +deriving Repr, Inhabited + +namespace EntityValidationRequest + +instance : Message EntityValidationRequest where + parseField (t : Tag) := do + match t.fieldNum with + | 1 => parseFieldElement t schema (update schema) + | 2 => parseFieldElement t entities (update entities) + | _ => let _ ← t.wireType.skip ; pure ignore + + merge x y := { + schema := Field.merge x.schema y.schema + entities := Field.merge x.entities y.entities + } + +end EntityValidationRequest + +end Cedar.Validation.Proto diff --git a/cedar-lean/CedarProto/EvaluationRequest.lean b/cedar-lean/CedarProto/EvaluationRequest.lean new file mode 100644 index 000000000..dd8664615 --- /dev/null +++ b/cedar-lean/CedarProto/EvaluationRequest.lean @@ -0,0 +1,56 @@ +/- + Copyright Cedar Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-/ + +import Cedar.Spec +import Protobuf.Message +import Protobuf.Structure + +-- Message Dependencies +import CedarProto.Request +import CedarProto.Entities +import CedarProto.Expr + +open Proto + +namespace Cedar.Spec +structure EvaluationRequest where + expr : Expr + request : Request + entities : Entities + expected : Option Value +deriving Inhabited, DecidableEq, Repr + +namespace EvaluationRequest + +instance : Message EvaluationRequest where + parseField (t : Proto.Tag) := do + match t.fieldNum with + | 1 => parseFieldElement t expr (update expr) + | 2 => parseFieldElement t request (update request) + | 3 => parseFieldElement t entities (update entities) + | 4 => parseFieldElement t expected (update expected) + | _ => let _ ← t.wireType.skip ; pure ignore + + merge x y := { + expr := Field.merge x.expr y.expr + request := Field.merge x.request y.request + entities := Field.merge x.entities y.entities + expected := Field.merge x.expected y.expected + } + +end EvaluationRequest + +end Cedar.Spec diff --git a/cedar-lean/CedarProto/RequestValidationRequest.lean b/cedar-lean/CedarProto/RequestValidationRequest.lean new file mode 100644 index 000000000..4b49ea1c3 --- /dev/null +++ b/cedar-lean/CedarProto/RequestValidationRequest.lean @@ -0,0 +1,51 @@ +/- + Copyright Cedar Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-/ + +import Cedar.Spec +import Protobuf.Message +import Protobuf.Structure + +-- Message Dependencies +import CedarProto.Schema +import CedarProto.Request + + +open Proto + +namespace Cedar.Validation.Proto + +structure RequestValidationRequest where + schema : Validation.Schema + request : Cedar.Spec.Request +deriving Repr, Inhabited + +namespace RequestValidationRequest + +instance : Message RequestValidationRequest where + parseField (t : Tag) := do + match t.fieldNum with + | 1 => parseFieldElement t schema (update schema) + | 2 => parseFieldElement t request (update request) + | _ => let _ ← t.wireType.skip ; pure ignore + + merge x y := { + schema := Field.merge x.schema y.schema + request := Field.merge x.request y.request + } + +end RequestValidationRequest + +end Cedar.Validation.Proto diff --git a/cedar-lean/Cli/Main.lean b/cedar-lean/Cli/Main.lean index 8f206fd6a..cdae49236 100644 --- a/cedar-lean/Cli/Main.lean +++ b/cedar-lean/Cli/Main.lean @@ -55,14 +55,16 @@ unsafe def main (args : List String) : IO Unit := IO.println response | "evaluate" => let request ← IO.FS.readFile filename + -- does not use evaluateDRT, because that just takes an `expected` + -- and returns true/false whether the result matched expected let response := evaluate request IO.println s!"{repr response}" | "validateRequest" => - let request ← IO.FS.readFile filename + let request ← IO.FS.readBinFile filename let response := validateRequestDRT request IO.println response | "validateEntities" => - let request ← IO.FS.readFile filename + let request ← IO.FS.readBinFile filename let response := validateEntitiesDRT request IO.println response | _ => printUsage s!"Invalid command `{command}` (expected `authorize`, `validate`, `validateRequest`, `validateEntities`, or `evaluate`)" diff --git a/cedar-lean/DiffTest/Main.lean b/cedar-lean/DiffTest/Main.lean index 6c6bcb2e3..2ee2a3f8d 100644 --- a/cedar-lean/DiffTest/Main.lean +++ b/cedar-lean/DiffTest/Main.lean @@ -87,22 +87,18 @@ def runAndTimeIO (f : IO α) : IO (Timed α) := do toString (Lean.toJson result) /-- - `req`: string containing JSON + `req`: binary protobuf for an `EvaluationRequest` returns a string containing JSON -/ -@[export evaluateDRT] unsafe def evaluateDRT (req : String) : String := +@[export evaluateDRT] unsafe def evaluateDRT (req : ByteArray) : String := let result : ParseResult (Timed Bool) := - match Lean.Json.parse req with + match (@Message.interpret? EvaluationRequest) req with | .error e => .error s!"evaluateDRT: failed to parse input: {e}" - | .ok json => do - let expr ← getJsonField json "expr" >>= jsonToExpr - let request ← getJsonField json "request" >>= jsonToRequest - let entities ← getJsonField json "entities" >>= jsonToEntities - let expected ← getJsonField json "expected" >>= jsonToOptionalValue - let result := runAndTime (λ () => evaluate expr request entities) + | .ok v => do + let result := runAndTime (λ () => evaluate v.expr v.request v.entities) let { data, duration } := unsafeBaseIO result - let data := match data, expected with + let data := match data, v.expected with | .error _, .none => true | .ok v₁, .some v₂ => v₁ == v₂ | _, _ => false @@ -116,37 +112,33 @@ def runAndTimeIO (f : IO α) : IO (Timed α) := do s!"partialEvaluateDRT: not supported {req}" /-- - `req`: string containing JSON + `req`: binary protobuf for an `EntityValidationRequest` returns a string containing JSON -/ -@[export validateEntitiesDRT] unsafe def validateEntitiesDRT (req : String) : String := +@[export validateEntitiesDRT] unsafe def validateEntitiesDRT (req : ByteArray) : String := let result : ParseResult (Timed EntityValidationResult) := - match Lean.Json.parse req with + match (@Message.interpret? EntityValidationRequest) req with | .error e => .error s!"validateEntitiesDRT: failed to parse input: {e}" - | .ok json => do - let schema ← getJsonField json "schema" >>= jsonToSchema - let entities ← getJsonField json "entities" >>= jsonToEntities - let actionEntities := (schema.acts.mapOnValues actionSchemaEntryToEntityData) - let entities := Cedar.Data.Map.make (entities.kvs ++ actionEntities.kvs) - let schema := updateSchema schema actionEntities + | .ok v => do + let actionEntities := (v.schema.acts.mapOnValues actionSchemaEntryToEntityData) + let entities := Cedar.Data.Map.make (v.entities.kvs ++ actionEntities.kvs) + let schema := updateSchema v.schema actionEntities let result := runAndTime (λ () => Cedar.Validation.validateEntities schema entities ) .ok (unsafeBaseIO result) toString (Lean.toJson result) /-- - `req`: string containing JSON + `req`: binary protobuf for a `RequestValidationRequest` returns a string containing JSON -/ -@[export validateRequestDRT] unsafe def validateRequestDRT (req : String) : String := +@[export validateRequestDRT] unsafe def validateRequestDRT (req : ByteArray) : String := let result : ParseResult (Timed RequestValidationResult) := - match Lean.Json.parse req with + match (@Message.interpret? RequestValidationRequest) req with | .error e => .error s!"validateRequestDRT: failed to parse input: {e}" - | .ok json => do - let schema ← getJsonField json "schema" >>= jsonToSchema - let request ← getJsonField json "request" >>= jsonToRequest - let result := runAndTime (λ () => Cedar.Validation.validateRequest schema request ) + | .ok v => do + let result := runAndTime (λ () => Cedar.Validation.validateRequest v.schema v.request ) .ok (unsafeBaseIO result) toString (Lean.toJson result) diff --git a/cedar-lean/Protobuf/Structures.lean b/cedar-lean/Protobuf/Structures.lean index e50a3a754..da51c05e9 100644 --- a/cedar-lean/Protobuf/Structures.lean +++ b/cedar-lean/Protobuf/Structures.lean @@ -25,9 +25,6 @@ Various Protobuf Structures, likely will reorganize later namespace Proto -structure MessageSchema where - schema : Std.HashMap Nat PType - structure Tag where fieldNum : Nat wireType : WireType @@ -72,7 +69,7 @@ def parse : BParsec Tag := do else if wt_uint = 3 then pure WireType.SGROUP else if wt_uint = 4 then pure WireType.EGROUP else if wt_uint = 5 then pure WireType.I32 - else throw "Unexcepted Wire Type" + else throw "Unexpected Wire Type" have field_num := element >>> 3 pure (Tag.mk field_num.toNat wire_type)