Skip to content
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
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
2 changes: 1 addition & 1 deletion cedar-policy-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ cedar-policy-formatter = { version = "=3.1.0", path = "../cedar-policy-formatter
clap = { version = "4", features = ["derive", "env"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
miette = { version = "5.9.0", features = ["fancy"] }
miette = { version = "7.1.0", features = ["fancy"] }
thiserror = "1.0"

[features]
Expand Down
2 changes: 1 addition & 1 deletion cedar-policy-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ thiserror = "1.0"
smol_str = { version = "0.2", features = ["serde"] }
stacker = "0.1.15"
arbitrary = { version = "1", features = ["derive"], optional = true }
miette = { version = "5.9.0", features = ["serde"] }
miette = { version = "7.1.0", features = ["serde"] }

# decimal extension requires regex
regex = { version = "1.8", features = ["unicode"], optional = true }
Expand Down
1 change: 0 additions & 1 deletion cedar-policy-core/src/parser/text_to_cst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ lalrpop_mod!(
);

use super::*;
use node::Node;
use std::sync::Arc;

/// This helper function calls a generated parser, collects errors that could be
Expand Down
1 change: 0 additions & 1 deletion cedar-policy-core/src/transitive_closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
//! Module containing code to compute the transitive closure of a graph.
//! This is a generic utility, and not specific to Cedar.

use std::cmp::Eq;
use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Display};
use std::hash::Hash;
Expand Down
4 changes: 2 additions & 2 deletions cedar-policy-formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ repository = "https://github.com/cedar-policy/cedar"
[dependencies]
cedar-policy-core = { version = "=3.1.0", path = "../cedar-policy-core" }
pretty = "0.12.1"
logos = "0.13.0"
logos = "0.14.0"
itertools = "0.12"
smol_str = { version = "0.2", features = ["serde"] }
regex = { version= "1.9.1", features = ["unicode"] }
miette = { version = "5.9.0" }
miette = { version = "7.1.0" }
2 changes: 1 addition & 1 deletion cedar-policy-validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ cedar-policy-core = { version = "=3.1.0", path = "../cedar-policy-core" }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
serde_with = "3.0"
miette = "5.9.0"
miette = "7.1.0"
thiserror = "1.0"
itertools = "0.12"
unicode-security = "0.1.0"
Expand Down
9 changes: 8 additions & 1 deletion cedar-policy-validator/src/typecheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1865,7 +1865,14 @@ impl<'a> Typechecker<'a> {
.get_entity_type(&rhs_name)
.map(|ety| ety.descendants.contains(&lhs_name))
.unwrap_or(false);
if lhs_name == rhs_name || lhs_ty_in_rhs_ty {
// A schema may always declare that an action entity is a member of another action entity,
// regardless of their exact types (i.e., their namespaces), so we shouldn't treat it as an error.
let action_in_action = is_action_entity_type(&lhs_name)
&& is_action_entity_type(&rhs_name);
if lhs_name == rhs_name
|| action_in_action
|| lhs_ty_in_rhs_ty
{
TypecheckAnswer::success(type_of_in)
} else {
// We could actually just return `Type::False`, but this is incurs a larger Dafny proof update.
Expand Down
155 changes: 154 additions & 1 deletion cedar-policy-validator/src/typecheck/test_namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#![cfg(test)]
// GRCOV_STOP_COVERAGE

use cool_asserts::assert_matches;
use serde_json::json;
use std::str::FromStr;
use std::vec;
Expand All @@ -35,7 +36,7 @@ use super::test_utils::{
use crate::{
type_error::TypeError,
types::{EntityLUB, Type},
AttributeAccess, SchemaFragment, ValidatorSchema,
AttributeAccess, SchemaError, SchemaFragment, ValidatorSchema,
};

fn namespaced_entity_type_schema() -> SchemaFragment {
Expand Down Expand Up @@ -526,3 +527,155 @@ fn namespaced_entity_is_wrong_type_when() {
)],
);
}

#[test]
fn multi_namespace_action_eq() {
let (schema, _) = SchemaFragment::from_str_natural(
r#"
action "Action" appliesTo { context: {} };
namespace NS1 { action "Action" appliesTo { context: {} }; }
namespace NS2 { action "Action" appliesTo { context: {} }; }
"#,
)
.unwrap();

assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"permit(principal, action == Action::"Action", resource);"#,
)
.unwrap(),
);
assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"permit(principal, action == NS1::Action::"Action", resource);"#,
)
.unwrap(),
);

let policy = parse_policy(
None,
r#"permit(principal, action, resource) when { NS1::Action::"Action" == NS2::Action::"Action" };"#,
)
.unwrap();
assert_policy_typecheck_fails(
schema.clone(),
policy.clone(),
vec![TypeError::impossible_policy(policy.condition())],
);
}

#[test]
fn multi_namespace_action_in() {
let (schema, _) = SchemaFragment::from_str_natural(
r#"
namespace NS1 { action "Group"; }
namespace NS2 { action "Group" in [NS1::Action::"Group"]; }
namespace NS3 {
action "Group" in [NS2::Action::"Group"];
action "Action" in [Action::"Group"] appliesTo { context: {} };
}
namespace NS4 { action "Group"; }
"#,
)
.unwrap();

assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"permit(principal, action in NS1::Action::"Group", resource);"#,
)
.unwrap(),
);
assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"permit(principal, action in NS2::Action::"Group", resource);"#,
)
.unwrap(),
);
assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"permit(principal, action in NS3::Action::"Group", resource);"#,
)
.unwrap(),
);
assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"permit(principal, action in NS3::Action::"Action", resource);"#,
)
.unwrap(),
);

let policy = parse_policy(
None,
r#"permit(principal, action in NS4::Action::"Group", resource);"#,
)
.unwrap();
assert_policy_typecheck_fails(
schema.clone(),
policy.clone(),
vec![TypeError::impossible_policy(policy.condition())],
);
}

#[test]
fn test_cedar_policy_642() {
let (schema, _) = SchemaFragment::from_str_natural(
r#"
namespace NS1 {
entity SystemEntity2 in SystemEntity1;
entity SystemEntity1, PrincipalEntity;
action Group1;
}
namespace NS2 {
entity SystemEntity1 in NS1::SystemEntity2;
action "Group1" in NS1::Action::"Group1";
action "Action1" in Action::"Group1" appliesTo {
principal: [NS1::PrincipalEntity],
resource: [NS2::SystemEntity1],
};
}
"#,
)
.unwrap();

assert_policy_typechecks(
schema.clone(),
parse_policy(
None,
r#"
permit(
principal in NS1::PrincipalEntity::"user1",
action in NS1::Action::"Group1",
resource in NS1::SystemEntity1::"entity1"
);"#,
)
.unwrap(),
);
}

#[test]
fn multi_namespace_action_group_cycle() {
let (schema, _) = SchemaFragment::from_str_natural(
r#"
namespace A { action "Act" in C::Action::"Act"; }
namespace B { action "Act" in A::Action::"Act"; }
namespace C { action "Act" in B::Action::"Act"; }
"#,
)
.unwrap();
assert_matches!(
ValidatorSchema::try_from(schema),
Err(SchemaError::CycleInActionHierarchy(_))
)
}
2 changes: 2 additions & 0 deletions cedar-policy/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `ValidationResult` methods `validation_errors` and `validation_warnings`, along with
`confusable_string_checker`, now return iterators with static lifetimes instead of
custom lifetimes, fixing build for latest nightly Rust. (#712)
- Validation for the `in` operator to no longer reports an error when comparing actions
in different namespaces. (#704, resolving #642)

## [3.1.0] - 2024-03-08
Cedar Language Version: 3.1.0
Expand Down
2 changes: 1 addition & 1 deletion cedar-policy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = "1.0"
lalrpop-util = { version = "0.20.0", features = ["lexer"] }
itertools = "0.12"
miette = "5.9.0"
miette = "7.1.0"
thiserror = "1.0"
smol_str = { version = "0.2", features = ["serde"] }
dhat = { version = "0.3.2", optional = true }
Expand Down