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}