Skip to content

Commit

Permalink
Level validation Rust implementation (RFC 76) (#1146)
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Wells <anmwells@amazon.com>
  • Loading branch information
andrewmwells-amazon authored Oct 3, 2024
1 parent 9b45bae commit 2de6db8
Show file tree
Hide file tree
Showing 13 changed files with 730 additions and 8 deletions.
1 change: 1 addition & 0 deletions cedar-policy-validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ arbitrary = ["dep:arbitrary", "cedar-policy-core/arbitrary"]

# Experimental features.
partial-validate = []
level-validate = []
wasm = ["serde-wasm-bindgen", "tsify", "wasm-bindgen"]
entity-manifest = []
entity-tags = []
Expand Down
6 changes: 6 additions & 0 deletions cedar-policy-validator/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ pub enum ValidationError {
#[diagnostic(transparent)]
#[cfg_attr(not(feature = "entity-tags"), allow(dead_code))]
InternalInvariantViolation(#[from] validation_errors::InternalInvariantViolation),
#[cfg(feature = "level-validate")]
/// If a entity dereference level was provided, the policies cannot deref
/// more than `level` hops away from PARX
#[error(transparent)]
#[diagnostic(transparent)]
EntityDerefLevelViolation(#[from] validation_errors::EntityDerefLevelViolation),
}

impl ValidationError {
Expand Down
77 changes: 77 additions & 0 deletions cedar-policy-validator/src/diagnostics/validation_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use miette::Diagnostic;
use thiserror::Error;

use std::fmt::Display;
use std::ops::{Add, Neg};

use cedar_policy_core::impl_diagnostic_from_source_loc_opt_field;
use cedar_policy_core::parser::Loc;
Expand Down Expand Up @@ -448,6 +449,82 @@ impl Diagnostic for HierarchyNotRespected {
}
}

#[derive(Debug, Clone, Hash, Eq, PartialEq, Error, Copy, Ord, PartialOrd)]
/// Represents how many entity dereferences can be applied to a node.
pub struct EntityDerefLevel {
/// A negative value `-n` represents `n` too many dereferences
pub level: i64,
}

impl Display for EntityDerefLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
write!(f, "{}", self.level)
}
}

impl From<u32> for EntityDerefLevel {
fn from(value: u32) -> Self {
EntityDerefLevel {
level: value as i64,
}
}
}

impl Default for EntityDerefLevel {
fn default() -> Self {
Self { level: 0 }
}
}

impl Add for EntityDerefLevel {
type Output = Self;

fn add(self, rhs: Self) -> Self::Output {
EntityDerefLevel {
level: self.level + rhs.level,
}
}
}

impl Neg for EntityDerefLevel {
type Output = Self;

fn neg(self) -> Self::Output {
EntityDerefLevel { level: -self.level }
}
}

impl EntityDerefLevel {
/// Decrement the entity deref level
pub fn decrement(&self) -> Self {
EntityDerefLevel {
level: self.level - 1,
}
}
}

/// Structure containing details about entity dereference level violation
#[derive(Debug, Clone, Hash, Eq, PartialEq, Error)]
#[error("for policy `{policy_id}`, the maximum allowed level {allowed_level} is violated. Actual level is {}", (allowed_level.add(actual_level.neg())))]
pub struct EntityDerefLevelViolation {
/// Source location
pub source_loc: Option<Loc>,
/// Policy ID where the error occurred
pub policy_id: PolicyID,
/// The maximum level allowed by the schema
pub allowed_level: EntityDerefLevel,
/// The actual level this policy uses
pub actual_level: EntityDerefLevel,
}

impl Diagnostic for EntityDerefLevelViolation {
impl_diagnostic_from_source_loc_opt_field!(source_loc);

fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
Some(Box::new(format!("Consider increasing the level")))
}
}

/// The policy uses an empty set literal in a way that is forbidden
#[derive(Debug, Clone, Hash, Eq, PartialEq, Error)]
#[error("for policy `{policy_id}`, empty set literals are forbidden in policies")]
Expand Down
2 changes: 1 addition & 1 deletion cedar-policy-validator/src/entity_manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ pub fn compute_entity_manifest(
// using static analysis
compute_root_trie(&typechecked_expr, policy.id())
}
PolicyCheck::Irrelevant(_) => {
PolicyCheck::Irrelevant(_, _) => {
// this policy is irrelevant, so we need no data
Ok(RootAccessTrie::new())
}
Expand Down
Loading

0 comments on commit 2de6db8

Please sign in to comment.