Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove unreleased JSON serialization code from the CLI #1366

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
295 changes: 136 additions & 159 deletions cedar-policy-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,14 @@ pub enum Commands {
New(NewArgs),
/// Partially evaluate an authorization request
PartiallyAuthorize(PartiallyAuthorizeArgs),
/// Ouput a JSON file for consumption by Lean
#[command(subcommand)]
WriteDRTJson(serialization::AnalysisCommands),
/// Output a protobuf binary file for consumption by Lean
#[cfg(feature = "protobufs")]
#[command(subcommand)]
WriteDRTProto(serialization::AnalysisCommands),
WriteDRTProto(protobufs::AnalysisCommands),
Comment on lines 121 to +124
Copy link
Contributor

@john-h-kastner-aws john-h-kastner-aws Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question related to existing code, but worth thinking about before releaseing protbuf code. I guess I don't really know what protofbuf functionality was added to the CLI in the first place, but how does the variant name (WriteDRTProto) relate to inner struct (AnalysisCommands)? Also, is this protobuf format still DRT specific, or should we rename this to something more general before release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming was done by #1326, I think the relationship is that AnalysisCommands is a list of the protobuf formats supported by WriteDRTProto (today, just Equivalence), all of which relate to analysis (at least today). I agree this should be changed prior to release. Let's track that in #1348; I see you've already linked this comment there

/// Output a protobuf binary file for consumption by Lean
#[cfg(feature = "protobufs")]
#[command(subcommand)]
WriteDRTProtoFromJSON(serialization::AnalyzeCommandsFromJson),
WriteDRTProtoFromJSON(protobufs::AnalyzeCommandsFromJson),
/// Print Cedar language version
LanguageVersion,
}
Expand Down Expand Up @@ -1603,17 +1600,25 @@ fn execute_partial_request(
}
}

pub mod serialization {
#[cfg(feature = "protobufs")]
pub mod protobufs {
// PANIC SAFETY experimental feature
#![allow(clippy::unwrap_used)]
// PANIC SAFETY experimental feature
#![allow(clippy::expect_used)]

use crate::{proto, CedarExitCode};
use cedar_policy_core::{ast::PolicySet, extensions::Extensions, parser::parse_policyset};
use cedar_policy_validator::CedarSchemaError;
use clap::{Args, Subcommand};
use serde::Serialize;
use prost::Message;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use thiserror::Error;

use crate::CedarExitCode;

/// Captures all possible errors in CLI operations in the `serialization` module
/// Captures all possible errors in CLI operations in the `protobufs` module
#[derive(Debug, Error)]
pub enum CliError {
/// Error opening or reading a file
Expand Down Expand Up @@ -1754,176 +1759,148 @@ pub mod serialization {
}
}

#[cfg(feature = "protobufs")]
pub mod protobuf {
// PANIC SAFETY experimental feature
#![allow(clippy::unwrap_used)]
// PANIC SAFETY experimental feature
#![allow(clippy::expect_used)]

use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use super::{
read_policies_from_file, AnalysisCommands, AnalyzeCommandsFromJson,
AnalyzeCommandsFromJsonArgs, EquivRequest,
};
use super::{EquivalenceArgs, Result};
use crate::serialization::read_schema_from_file;
use crate::{proto, CedarExitCode};
use cedar_policy_core::ast::PolicySet;
use cedar_policy_core::parser::parse_policyset;
use prost::Message;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize)]
pub struct ValidationRequest<'a> {
pub schema: &'a cedar_policy_validator::ValidatorSchema,
pub policies: &'a PolicySet,
pub mode: cedar_policy_validator::ValidationMode,
}
#[derive(Debug, Serialize)]
pub struct ValidationRequest<'a> {
pub schema: &'a cedar_policy_validator::ValidatorSchema,
pub policies: &'a PolicySet,
pub mode: cedar_policy_validator::ValidationMode,
}

impl From<ValidationRequest<'_>> for proto::ValidationRequestMsg {
fn from(v: ValidationRequest<'_>) -> Self {
Self {
schema: Some(cedar_policy_validator::proto::ValidatorSchema::from(
v.schema,
)),
policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
v.policies,
)),
mode: cedar_policy_validator::proto::ValidationMode::from(&v.mode).into(),
}
impl From<ValidationRequest<'_>> for proto::ValidationRequestMsg {
fn from(v: ValidationRequest<'_>) -> Self {
Self {
schema: Some(cedar_policy_validator::proto::ValidatorSchema::from(
v.schema,
)),
policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
v.policies,
)),
mode: cedar_policy_validator::proto::ValidationMode::from(&v.mode).into(),
}
}
}

impl From<EquivRequest<'_>> for proto::EquivRequestMsg {
fn from(v: EquivRequest<'_>) -> Self {
Self {
schema: Some(cedar_policy_validator::proto::ValidatorSchema::from(
v.schema,
)),
old_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
v.old_policies,
)),
new_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
v.new_policies,
)),
}
impl From<EquivRequest<'_>> for proto::EquivRequestMsg {
fn from(v: EquivRequest<'_>) -> Self {
Self {
schema: Some(cedar_policy_validator::proto::ValidatorSchema::from(
v.schema,
)),
old_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
v.old_policies,
)),
new_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
v.new_policies,
)),
}
}
}

pub fn read_equivalence_drt_from_files(
args: EquivalenceArgs,
) -> Result<proto::EquivRequestMsg> {
let schema = &read_schema_from_file(&args.schema_file)?;
let old_policies = &read_policies_from_file(&args.old_policies_file)?;
let new_policies = &read_policies_from_file(&args.new_policies_file)?;

let equiv_request = EquivRequest {
schema,
old_policies,
new_policies,
};
let equiv_request_proto = proto::EquivRequestMsg::from(equiv_request);
Ok(equiv_request_proto)
}
pub fn read_equivalence_drt_from_files(
args: EquivalenceArgs,
) -> Result<proto::EquivRequestMsg> {
let schema = &read_schema_from_file(&args.schema_file)?;
let old_policies = &read_policies_from_file(&args.old_policies_file)?;
let new_policies = &read_policies_from_file(&args.new_policies_file)?;

let equiv_request = EquivRequest {
schema,
old_policies,
new_policies,
};
let equiv_request_proto = proto::EquivRequestMsg::from(equiv_request);
Ok(equiv_request_proto)
}

pub fn write_drt_proto_for_equivalence_from_files(args: EquivalenceArgs) -> Result<()> {
let equiv_request_proto: proto::EquivRequestMsg =
read_equivalence_drt_from_files(args)?;
write_drt_proto_for_equivalence(equiv_request_proto, "equiv_request.binpb".into())
}
pub fn write_drt_proto_for_equivalence_from_files(args: EquivalenceArgs) -> Result<()> {
let equiv_request_proto: proto::EquivRequestMsg = read_equivalence_drt_from_files(args)?;
write_drt_proto_for_equivalence(equiv_request_proto, "equiv_request.binpb".into())
}

#[derive(Debug, Deserialize)]
struct ComparisonRequest {
schema: String,
old_policy_set: String,
new_policy_set: String,
}
#[derive(Debug, Deserialize)]
struct ComparisonRequest {
schema: String,
old_policy_set: String,
new_policy_set: String,
}

pub fn read_equivalence_drt_from_json(
args: AnalyzeCommandsFromJsonArgs,
) -> Result<proto::EquivRequestMsg> {
use std::str::FromStr;
pub fn read_equivalence_drt_from_json(
args: AnalyzeCommandsFromJsonArgs,
) -> Result<proto::EquivRequestMsg> {
use std::str::FromStr;

let comparison_request: ComparisonRequest =
serde_json::from_str(args.data.as_ref()).expect("Failed to parse");
let comparison_request: ComparisonRequest =
serde_json::from_str(args.data.as_ref()).expect("Failed to parse");

let schema =
cedar_policy_validator::ValidatorSchema::from_str(&comparison_request.schema)
.expect("Failed to deserialize schema");
let schema = cedar_policy_validator::ValidatorSchema::from_str(&comparison_request.schema)
.expect("Failed to deserialize schema");

let old_policies = parse_policyset(&comparison_request.old_policy_set).unwrap();
let old_policies = parse_policyset(&comparison_request.old_policy_set).unwrap();

let new_policies = parse_policyset(&comparison_request.new_policy_set).unwrap();
let new_policies = parse_policyset(&comparison_request.new_policy_set).unwrap();

Ok(proto::EquivRequestMsg {
schema: Some(cedar_policy_validator::proto::ValidatorSchema::from(
&schema,
)),
old_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
&old_policies,
)),
new_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
&new_policies,
)),
})
}
Ok(proto::EquivRequestMsg {
schema: Some(cedar_policy_validator::proto::ValidatorSchema::from(
&schema,
)),
old_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
&old_policies,
)),
new_policies: Some(cedar_policy_core::ast::proto::LiteralPolicySet::from(
&new_policies,
)),
})
}

pub fn write_drt_proto_for_equivalence_from_json(
args: AnalyzeCommandsFromJsonArgs,
) -> Result<()> {
let output_path = args.output_path.clone();
let equiv_request_proto: proto::EquivRequestMsg = read_equivalence_drt_from_json(args)?;
write_drt_proto_for_equivalence(equiv_request_proto, output_path)
}
pub fn write_drt_proto_for_equivalence_from_json(
args: AnalyzeCommandsFromJsonArgs,
) -> Result<()> {
let output_path = args.output_path.clone();
let equiv_request_proto: proto::EquivRequestMsg = read_equivalence_drt_from_json(args)?;
write_drt_proto_for_equivalence(equiv_request_proto, output_path)
}

pub fn write_drt_proto_for_equivalence(
equiv_request_proto: proto::EquivRequestMsg,
output_location: PathBuf,
) -> Result<()> {
let mut buf: Vec<u8> = vec![];
buf.reserve(equiv_request_proto.encoded_len());
equiv_request_proto
.encode(&mut buf)
.expect("Serialization failed");

let mut file = File::create(output_location).unwrap();
// Write a slice of bytes to the file
file.write_all(&buf).unwrap();

Ok(())
}
pub fn write_drt_proto_for_equivalence(
equiv_request_proto: proto::EquivRequestMsg,
output_location: PathBuf,
) -> Result<()> {
let mut buf: Vec<u8> = vec![];
buf.reserve(equiv_request_proto.encoded_len());
equiv_request_proto
.encode(&mut buf)
.expect("Serialization failed");

let mut file = File::create(output_location).unwrap();
// Write a slice of bytes to the file
file.write_all(&buf).unwrap();

Ok(())
}

pub fn write_drt_proto(acmd: AnalysisCommands) -> CedarExitCode {
let res = match acmd {
AnalysisCommands::Equivalence(args) => {
write_drt_proto_for_equivalence_from_files(args)
}
};
match res {
Ok(()) => CedarExitCode::Success,
Err(e) => {
eprintln!("{e}");
CedarExitCode::Failure
}
pub fn write_drt_proto(acmd: AnalysisCommands) -> CedarExitCode {
let res = match acmd {
AnalysisCommands::Equivalence(args) => write_drt_proto_for_equivalence_from_files(args),
};
match res {
Ok(()) => CedarExitCode::Success,
Err(e) => {
eprintln!("{e}");
CedarExitCode::Failure
}
}
}

pub fn write_drt_proto_from_json(acmd: AnalyzeCommandsFromJson) -> CedarExitCode {
let res = match acmd {
AnalyzeCommandsFromJson::Equivalence(args) => {
write_drt_proto_for_equivalence_from_json(args)
}
};
match res {
Ok(()) => CedarExitCode::Success,
Err(e) => {
eprintln!("{e}");
CedarExitCode::Failure
}
pub fn write_drt_proto_from_json(acmd: AnalyzeCommandsFromJson) -> CedarExitCode {
let res = match acmd {
AnalyzeCommandsFromJson::Equivalence(args) => {
write_drt_proto_for_equivalence_from_json(args)
}
};
match res {
Ok(()) => CedarExitCode::Success,
Err(e) => {
eprintln!("{e}");
CedarExitCode::Failure
}
}
}
Expand Down
Loading
Loading