use crate::{CedarExitCode, PoliciesArgs, SchemaArgs};
use cedar_policy::Validator;
use clap::{Args, ValueEnum};
use miette::Report;
#[derive(Args, Debug)]
pub struct ValidateArgs {
#[command(flatten)]
pub schema: SchemaArgs,
#[command(flatten)]
pub policies: PoliciesArgs,
#[arg(long)]
pub deny_warnings: bool,
#[arg(long, value_enum, default_value_t = ValidationMode::Strict)]
pub validation_mode: ValidationMode,
#[arg(long)]
pub level: Option<u32>,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum ValidationMode {
Strict,
Permissive,
Partial,
}
pub fn validate(args: &ValidateArgs) -> CedarExitCode {
let mode = match args.validation_mode {
ValidationMode::Strict => cedar_policy::ValidationMode::Strict,
ValidationMode::Permissive => {
#[cfg(not(feature = "permissive-validate"))]
{
eprintln!("Error: arguments include the experimental option `--validation-mode permissive`, but this executable was not built with `permissive-validate` experimental feature enabled");
return CedarExitCode::Failure;
}
#[cfg(feature = "permissive-validate")]
cedar_policy::ValidationMode::Permissive
}
ValidationMode::Partial => {
#[cfg(not(feature = "partial-validate"))]
{
eprintln!("Error: arguments include the experimental option `--validation-mode partial`, but this executable was not built with `partial-validate` experimental feature enabled");
return CedarExitCode::Failure;
}
#[cfg(feature = "partial-validate")]
cedar_policy::ValidationMode::Partial
}
};
let pset = match args.policies.get_policy_set() {
Ok(pset) => pset,
Err(e) => {
println!("{e:?}");
return CedarExitCode::Failure;
}
};
let schema = match args.schema.get_schema() {
Ok(schema) => schema,
Err(e) => {
println!("{e:?}");
return CedarExitCode::Failure;
}
};
let validator = Validator::new(schema);
let result = if let Some(level) = args.level {
validator.validate_with_level(&pset, mode, level)
} else {
validator.validate(&pset, mode)
};
if !result.validation_passed()
|| (args.deny_warnings && !result.validation_passed_without_warnings())
{
println!(
"{:?}",
Report::new(result).wrap_err("policy set validation failed")
);
CedarExitCode::ValidationFailure
} else {
println!(
"{:?}",
Report::new(result).wrap_err("policy set validation passed")
);
CedarExitCode::Success
}
}