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