Skip to main content

Crate treetop_core

Crate treetop_core 

Source
Expand description

Usage example:

Here we declare a policy that allows “alice” to create a host if and only if the following conditions are met:

  • The host’s nameLabel set contains “example_domain”. This is created via regular expressions on the name from the initialize_host_patterns function.
  • The host’s IP address is within the network “10.0.0.0/24”.
  • The host’s name contains the letter ‘n’

Note that we do not require the host to have the nameLabel “webserver” for “alice” to create it.

use regex::Regex;
use std::sync::Arc;
use treetop_core::{Action, AttrValue, PolicyEngine, Request, Decision, User, Principal, Resource, RegexLabeler, LabelRegistryBuilder};
use sha2::{Digest, Sha256};

let policies = r#"
permit (
   principal == User::"alice",
   action == Action::"create_host",
   resource is Host
) when {
    resource.nameLabels.contains("in_domain") &&
    resource.ip.isInRange(ip("10.0.0.0/24")) &&
    resource.name like "*n*"
};
"#;

// Used to create attributes for hosts based on their names.
let patterns = vec![
    ("in_domain".to_string(), Regex::new(r"example\.com$").unwrap()),
    ("webserver".to_string(), Regex::new(r"^web-\d+").unwrap()),
];
let label_registry = LabelRegistryBuilder::new()
    .add_labeler(Arc::new(RegexLabeler::new(
        "Host",
        "name",
        "nameLabels",
        patterns.into_iter().collect(),
    )))
    .build();

let engine = PolicyEngine::new_from_str(&policies).unwrap()
    .with_label_registry(label_registry);

let request = Request {
   principal: Principal::User(User::new("alice", None, None)), // No groups, no namespace
   action: Action::new("create_host", None), // Action is not in a namespace
   resource: Resource::new("Host", "hostname.example.com")
    .with_attr("name", AttrValue::String("hostname.example.com".into()))
    .with_attr("ip", AttrValue::Ip("10.0.0.1".into()))
};

let decision = engine.evaluate(&request).unwrap();
assert!(matches!(decision, Decision::Allow { .. }));

// List all of alice's policies
let alice_policies = engine.list_policies_for_user("alice", &[], &[]).unwrap();
// This value is also seralizable to JSON
let json = serde_json::to_string(&alice_policies).unwrap();

// Check that the policy running is the expected version
let expected_hash = Sha256::digest(policies)
    .iter()
    .fold(String::with_capacity(64), |mut s, b| {
        use std::fmt::Write;
        write!(s, "{b:02x}").unwrap();
        s
    });
assert_eq!(engine.current_version().hash, expected_hash);

§Thread-Safe Sharing

For multithreaded applications, wrap PolicyEngine in Arc to share it across threads:

use std::sync::Arc;
use std::thread;

let engine = Arc::new(engine_base);
let engine_clone = Arc::clone(&engine);

let handle = thread::spawn(move || {
    // Evaluate policies in a background thread
    let request = Request {
        principal: Principal::User(User::new("user", None, None)),
        action: Action::new("read", None),
        resource: Resource::new("Document", "doc1"),
    };
    let _decision = engine_clone.evaluate(&request);
});

handle.join().unwrap();

Re-exports§

pub use types::Action;
pub use types::AttrValue;
pub use types::CedarType;
pub use types::Decision;
pub use types::DecisionDiagnostics;
pub use types::Group;
pub use types::Groups;
pub use types::PermitPolicies;
pub use types::PermitPolicy;
pub use types::PolicyEffectFilter;
pub use types::PolicyMatch;
pub use types::PolicyMatchReason;
pub use types::PolicyVersion;
pub use types::Principal;
pub use types::Request;
pub use types::RequestContext;
pub use types::Resource;
pub use types::User;
pub use types::UserPolicies;
pub use types::action_entity_uid;
pub use types::group_entity_uid;
pub use types::namespace_segments;
pub use types::resource_entity_uid;
pub use types::user_entity_uid;

Modules§

types
Data model types for requests and Cedar entity conversion.

Macros§

snapshot_decision
Helper macro to snapshot a decision with timestamp redaction. This keeps test snapshots stable by masking the time-varying loaded_at field.

Structs§

LabelRegistry
Implementation of the LabelRegistry.
LabelRegistryBuilder
Builder for creating a LabelRegistry with labelers.
PolicyEngine
The main engine handle. Thread-safe and cheaply cloneable.
RegexLabeler
A labeler that uses regular expressions for matching on resource attributes.
Schema
Object containing schema information used by the validator.

Enums§

PolicyError
Policy evaluation and validation errors.

Traits§

Labeler
Trait for objects that can label resources based on their attributes.

Functions§

build_info
compile_policy
Compile Cedar policy text into a PolicySet.
compile_policy_with_schema
Compile Cedar policy text into a PolicySet and validate against a schema.