cedar_policy_core/parser/
cst.rs

1/*
2 * Copyright 2022-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use super::node::ASTNode;
18use smol_str::SmolStr;
19// shortcut because we need CST nodes to potentially be empty,
20// for example, if part of it failed the parse, we can
21// still recover other parts
22type Node<N> = ASTNode<Option<N>>;
23
24/// The set of policy statements that forms an authorization policy
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct Policies(pub Vec<Node<Policy>>);
27
28/// Annotations: application-defined data, as a key-value pair
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Annotation {
31    /// key
32    pub key: Node<Ident>,
33    /// value
34    pub value: Node<Str>,
35}
36
37/// Literal strings
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum Str {
40    /// regular quoted string
41    String(SmolStr),
42    // this is not generated by the parser at time of comment,
43    // but left as future improvement and to clarify the
44    // validity of the above `String` form
45    /// poorly formed string
46    #[allow(unused)]
47    Invalid(SmolStr),
48}
49
50/// Policy statement, the main building block of the language
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct Policy {
53    /// Annotations
54    pub annotations: Vec<Node<Annotation>>,
55    /// policy effect
56    pub effect: Node<Ident>,
57    /// Variables
58    pub variables: Vec<Node<VariableDef>>,
59    /// Conditions
60    pub conds: Vec<Node<Cond>>,
61}
62
63/// The variable part of one of the main item of a policy
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct VariableDef {
66    /// identifier, expected:
67    /// principal, action, resource
68    pub variable: Node<Ident>,
69    /// type of entity
70    pub name: Option<Node<Name>>,
71    /// hierarchy of entity
72    pub ineq: Option<(RelOp, Node<Expr>)>,
73}
74
75/// Any identifier, including special ones
76#[derive(Debug, Clone, PartialEq, Eq)]
77#[allow(unused)] // definitional, or for later improvements
78pub enum Ident {
79    // Variables
80    /// principal
81    Principal,
82    /// action
83    Action,
84    /// resource
85    Resource,
86    /// context
87    Context,
88
89    // Other Identifiers
90    /// true
91    True,
92    /// false
93    False,
94    /// permit
95    Permit,
96    /// forbid
97    Forbid,
98    /// when
99    When,
100    /// unless
101    Unless,
102    /// in
103    In,
104    /// has
105    Has,
106    /// like
107    Like,
108    /// if
109    If,
110    /// then
111    Then,
112    /// else
113    Else,
114
115    // Regular identifiers
116    /// user-supplied, in the proper form
117    Ident(SmolStr),
118    // This is not generated from the parser a time of comment,
119    // but here for future improvement and to clarify
120    // the validity of the above `Ident` form
121    /// user-supplied, not in the proper form
122    Invalid(String),
123}
124
125/// Conditions: powerful extensions to a policy
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct Cond {
128    /// initial ident, expected to be "when" or "unless"
129    pub cond: Node<Ident>,
130    /// related expression. expected to not be `None`, but if it's `None`, that
131    /// indicates the body was empty (as in `when {}`), and we can report a good
132    /// error message
133    pub expr: Option<Node<Expr>>,
134}
135
136/// The main computation aspect of a policy, outer
137#[derive(Debug, Clone, PartialEq, Eq)]
138pub struct Expr {
139    /// expression content
140    pub expr: Box<ExprData>,
141}
142/// The main computation aspect of a policy, inner
143#[derive(Debug, Clone, PartialEq, Eq)]
144pub enum ExprData {
145    /// || Op
146    Or(Node<Or>),
147    /// if-then-else
148    If(Node<Expr>, Node<Expr>, Node<Expr>),
149}
150/// Logical Or
151#[derive(Debug, Clone, PartialEq, Eq)]
152pub struct Or {
153    /// a singleton is a wrapper for a higher-priority node
154    pub initial: Node<And>,
155    /// additional elements represent a chained `||` computation
156    pub extended: Vec<Node<And>>,
157}
158/// Logical And
159#[derive(Debug, Clone, PartialEq, Eq)]
160pub struct And {
161    /// a singleton is a wrapper for a higher-priority node
162    pub initial: Node<Relation>,
163    /// additional elements represent a chained `&&` computation
164    pub extended: Vec<Node<Relation>>,
165}
166/// Comparison relations
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub enum Relation {
169    /// Regular relations
170    Common {
171        /// a singleton is a wrapper for a higher-priority node
172        initial: Node<Add>,
173        /// additional elements represent chained `>`, `<`, etc. computation
174        extended: Vec<(RelOp, Node<Add>)>,
175    },
176    /// Built-in 'has' operation
177    Has {
178        /// element that may have a field
179        target: Node<Add>,
180        /// a field the element may have
181        field: Node<Add>,
182    },
183    /// Built-in 'like' operation
184    Like {
185        /// element to test
186        target: Node<Add>,
187        /// pattern to match on
188        pattern: Node<Add>,
189    },
190}
191
192/// The operation involved in a comparision
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194pub enum RelOp {
195    /// <
196    Less,
197    /// <=
198    LessEq,
199    /// >=
200    GreaterEq,
201    /// >
202    Greater,
203    /// !=
204    NotEq,
205    /// ==
206    Eq,
207    /// in
208    In,
209}
210
211/// Allowed Ops for Add
212#[derive(Debug, Clone, Copy, PartialEq, Eq)]
213pub enum AddOp {
214    /// +
215    Plus,
216    /// -
217    Minus,
218}
219
220/// Allowed Ops for Mult
221#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub enum MultOp {
223    /// *
224    Times,
225    /// /
226    Divide,
227    /// %
228    Mod,
229}
230
231/// Allowed Ops for Neg
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum NegOp {
234    /// count of `!`'s
235    Bang(u8),
236    /// too many `!`'s
237    OverBang,
238    /// count of `-`'s
239    Dash(u8),
240    /// too many `-`'s
241    OverDash,
242}
243
244/// Additive arithmetic
245#[derive(Debug, Clone, PartialEq, Eq)]
246pub struct Add {
247    /// a singleton is a wrapper for a higher-priority node
248    pub initial: Node<Mult>,
249    /// additional elements represent a chained `+`, `-`, etc. computation
250    pub extended: Vec<(AddOp, Node<Mult>)>,
251}
252/// Multiplicative arithmetic
253#[derive(Debug, Clone, PartialEq, Eq)]
254pub struct Mult {
255    /// a singleton is a wrapper for a higher-priority node
256    pub initial: Node<Unary>,
257    /// additional elements represent a chained `*`, `/`, etc. computation
258    pub extended: Vec<(MultOp, Node<Unary>)>,
259}
260/// Unary negations
261#[derive(Debug, Clone, PartialEq, Eq)]
262pub struct Unary {
263    /// the negation operation, if any
264    pub op: Option<NegOp>,
265    /// higher-priority node the negation is applied to
266    pub item: Node<Member>,
267}
268/// Members on a primary item, accessed with '.'
269#[derive(Debug, Clone, PartialEq, Eq)]
270pub struct Member {
271    /// Main element
272    pub item: Node<Primary>,
273    /// fields, indexes, etc.
274    pub access: Vec<Node<MemAccess>>,
275}
276/// Forms of members and their accessors
277#[derive(Debug, Clone, PartialEq, Eq)]
278pub enum MemAccess {
279    /// field identifier
280    Field(Node<Ident>),
281    /// function call
282    Call(Vec<Node<Expr>>),
283    /// index of a member
284    Index(Node<Expr>),
285}
286/// Low-level elements like literals
287#[derive(Debug, Clone, PartialEq, Eq)]
288pub enum Primary {
289    /// Literal
290    Literal(Node<Literal>),
291    /// References to entities
292    Ref(Node<Ref>),
293    /// Constructed elements with names
294    Name(Node<Name>),
295    /// Template Slots
296    Slot(Node<Slot>),
297    /// Parentheses
298    Expr(Node<Expr>),
299    /// Constructed array
300    EList(Vec<Node<Expr>>),
301    /// Constructed record
302    RInits(Vec<Node<RecInit>>),
303}
304
305/// UID and Type of named items
306#[derive(Debug, Clone, PartialEq, Eq)]
307pub struct Name {
308    /// path, like: "name0::name1::name"
309    pub path: Vec<Node<Ident>>,
310    /// Singleton name
311    pub name: Node<Ident>,
312}
313/// Reference to an entity
314#[derive(Debug, Clone, PartialEq, Eq)]
315pub enum Ref {
316    /// UID
317    Uid {
318        /// The path/type of an entity
319        path: Node<Name>,
320        /// EID, quoted name
321        eid: Node<Str>,
322    },
323    /// Lookup references
324    Ref {
325        /// The path/type of an entity
326        path: Node<Name>,
327        /// The indicated fields of the entity
328        rinits: Vec<Node<RefInit>>,
329    },
330}
331/// Elements in a ref: `field: data`
332#[derive(Debug, Clone, PartialEq, Eq)]
333pub struct RefInit(pub Node<Ident>, pub Node<Literal>);
334/// Elements of records: `field_from_expr: data_from_expr`
335#[derive(Debug, Clone, PartialEq, Eq)]
336pub struct RecInit(pub Node<Expr>, pub Node<Expr>);
337
338/// Raw values
339#[derive(Debug, Clone, PartialEq, Eq)]
340pub enum Literal {
341    /// true
342    True,
343    /// false
344    False,
345    /// some integer
346    Num(u64),
347    /// some String
348    Str(Node<Str>),
349}
350
351/// Template Slots
352#[derive(Debug, Clone, PartialEq, Eq)]
353pub enum Slot {
354    /// Slot for Principal Constraints
355    Principal,
356    /// Slot for Resource Constraints
357    Resource,
358}
359
360impl Slot {
361    /// Check if a slot matches a head variable.
362    pub fn matches(&self, var: crate::ast::Var) -> bool {
363        matches!(
364            (self, var),
365            (Slot::Principal, crate::ast::Var::Principal)
366                | (Slot::Resource, crate::ast::Var::Resource)
367        )
368    }
369}