Polar Language Reference

Reference guides for the Polar policy language.

Polar Syntax

A brief description of the core syntax elements of Polar.

Rust Types in Polar
Working with Rust Types Oso’s Rust authorization library allows you to write policy rules over Rust types directly. This document explains how different Rust types can be used in Oso policies. Note More detailed examples of working with application objects can be found in our Guides. Structs + Enums Rust structs and enums can be registered with Oso, which lets you pass them in and access their methods and fields in your policy (see Application Types). Rust structs can also be constructed from inside an Oso policy using the new operator if a type constructor is provided at registration. Numbers and Booleans Polar supports integer and floating point real numbers, as well as booleans (see Primitive Types). Strings Rust Strings are mapped to Polar strings. Many of Rust’s String methods may be called in policies: allow(actor, action, resource) if actor.username.ends_with("example.com"); #[derive(Clone, PolarClass)] struct User { #[polar(attribute)] pub username: String } oso.register_class(User::get_polar_class())?; let user = User{username: "alice@example.com".to_owned()}; assert!(oso.is_allowed(user, "foo", "bar")?); Warning Polar does not support methods that mutate strings in place. Vec Vec<T> maps to a Polar list, given that T: ToPolar. Implementations also exist to convert LinkedList, VecDeque, BinaryHeap, HashSet, and BTreeSetto and from Polar lists, but lists are treated as Vec<T> when calling methods. Currently, no methods on Vec are exposed to Polar. allow(actor, action, resource) if "HR" in actor.groups; #[derive(Clone, PolarClass)] struct User { #[polar(attribute)] pub groups: Vec<String>, } oso.register_class(User::get_polar_class())?; let user = User { groups: vec!["HR".to_string(), "payroll".to_string()] }; assert!(oso.is_allowed(user, "foo", "bar")?); Warning Polar does not support methods that mutate lists in place unless the list is also returned from the method. Rust methods like Vec::get may be used for random access to list elements, but there is currently no Polar syntax that is equivalent to the Rust expression user.groups[1]. To access the elements of a list without using a method, you may iterate over it with the in operator or destructure it with pattern matching. HashMap A Rust HashMap maps to a Polar dictionary but requires that the HashMap key is a String. Implementations also exist to convert BTreeMaps to and from Polar dictionaries, but dictionaries are treated as HashMap when calling methods. allow(actor, action, resource) if actor.roles.project1 = "admin"; #[derive(Clone, PolarClass)] struct User { #[polar(attribute)] pub roles: HashMap<String, String>, } oso.register_class(User::get_polar_class())?; let user = User { roles: maplit::hashmap!{ "project1".to_string() => "admin".to_string() }}; assert!(oso.is_allowed(user, "foo", "bar")?); Likewise, dictionaries constructed in Polar may be passed into Rust methods. Iterators You may iterate over a Rust iterator using Polar’s in operator: allow(actor, action, resource) if "payroll" in actor.get_groups(); #[derive(Clone, PolarClass)] struct User { groups: Vec<String>, } oso.register_class( User::get_polar_class_builder() .add_iterator_method("get_groups", |u: &User| u.groups.clone().into_iter()) .build(), ) .unwrap(); let user = User { groups: vec!["HR".to_string(), "payroll".to_string()], }; assert!(oso.is_allowed(user, "foo", "bar")?); Options The Rust type Option<T> is registered as a class. You can use unwrap() on an option in a policy, but it’s safer to use the in operator, which will return 0 or 1 values depending on whether the value is None or Some(T) respectively. The Option variant None is registered as the Polar constant nil. If a Rust method can return None, you may want to compare the result to nil: allow(actor, action, resource) if "Jimmy" in actor.nickname or actor.get_optional() != nil; #[derive(Clone, PolarClass)] struct User { #[polar(attribute)] nickname: Option<String>, } oso.register_class( User::get_polar_class_builder() .add_method("get_optional", |u: &User| None) .build(), ) .unwrap(); let user = User { nickname: Some("Jimmy".to_string()), }; assert!(oso.is_allowed(user, "foo", "bar")?); Rust → Polar Types Summary Rust type Polar type i32, i64, usize Integer f32, f64 Float bool Boolean String, &'static str, str String HashMap, BTreeMap Dictionary Vec, LinkedList, VecDeque BinaryHeap, HashSet, BTreeSet List