Skip to content

Commit d7ff80f

Browse files
committed
generalized version
Signed-off-by: oflatt <[email protected]>
1 parent 7b63a12 commit d7ff80f

File tree

1 file changed

+36
-42
lines changed

1 file changed

+36
-42
lines changed

text/0074/0074-entity-slicing.md

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -217,53 +217,54 @@ The merge operator for access paths is straightforward. First, convert all acces
217217

218218
## Computing access paths
219219

220-
This section proposes a simple static analysis that soundly computes all of the necessary access paths for a Cedar expression.
221-
While it’s possible to soundly handle all Cedar expressions, we simplify the problem by rejecting Cedar programs unless they follow the following grammar:
222-
223-
224-
```
225-
<expr> = <datapath-expr>
226-
<datapath-expr> in <expr>
227-
<expr> + <expr>
228-
if <expr> { <expr> } { <expr> }
229-
... all other Cedar operators not mentioned by datapath-expr
230-
231-
<datapath-expr> = <datapath-expr>.<field>
232-
<datapath-expr> has <field>
233-
<variable>
234-
<entity literal>
235-
236-
<variable> = principal
237-
resource
238-
action
239-
context
240-
220+
This section proposes a simple static analysis that soundly computes all of the necessary access paths for a Cedar expression.
221+
Given a Cedar expression, the analysis produces a pair (`HashMap<EntityRoot, AccessTrie>`, `WrappedAccessPaths`).
222+
The first value is the accumulated trie of data that needs to be loaded.
223+
The second value is the "live" access paths that need to be considered for the particular expression.
224+
225+
`WrappedAccessPaths` represents multiple potential access paths, soundly over-approximating the execution of a cedar expression.
226+
Since Cedar expressions may be record literals, the access paths are wrapped in corresponding record literals in the analysis:
227+
228+
```rust
229+
/// This allows the Entity Manifest to soundly handle
230+
/// data that is wrapped in record or set literals.
231+
#[derive(Debug, Clone, PartialEq, Eq, Default)]
232+
pub(crate) enum WrappedAccessPaths {
233+
/// No access paths are needed.
234+
#[default]
235+
Empty,
236+
/// A single access path, starting with a cedar variable.
237+
AccessPath(AccessPath),
238+
/// The union of two [`WrappedAccessPaths`], denoting that
239+
/// all access paths from both are required.
240+
/// This is useful for join points in the analysis (`if`, set literals, ect)
241+
Union(Box<WrappedAccessPaths>, Box<WrappedAccessPaths>),
242+
/// A record literal, each field having access paths.
243+
RecordLiteral(HashMap<SmolStr, Box<WrappedAccessPaths>>),
244+
/// A set literal containing access paths.
245+
/// Used to note that this type is wrapped in a literal set.
246+
SetLiteral(Box<WrappedAccessPaths>),
247+
}
241248
```
242249

250+
The analysis is bottom-up traveral of cedar expressions.
251+
Most operators are strait-forward to analyze, but there are some special cases to get right:
243252

244-
The grammar partitions Cedar expressions into **datapath expressions** and all other Cedar operators.
245-
On the LHS of `in`, `.`, and `has`, expressions involving `in`, `+`, `if-then-else`, and most other Cedar functions/operators are not allowed; only Cedar variables, entity literals, and `.` or `has` expressions are allowed.
246-
247-
The partition is reasonable since, in practice, users do not interleave datapath expressions with other operators.
248-
Here are examples of Cedar expressions rejected by this grammar:
249-
250-
251-
```
252-
{ "myfield": principal.name }.myfield
253-
(if principal.ismanager then { "myfield" : 2 } else { "myfield": 3 }).myfield
254-
(if principal has mobilePhone then principal.mobilePhone else principal.workPhone).zipCode
255-
```
253+
1. For entity or struct dereferences, be sure to add to all `WrappedAccessPaths`.
254+
2. For equality between records (`==` or `.contains`, `.containsAny`, and `.containsAll`), all fields in the type need to be added to the access paths.
255+
3. For if statements, the `Union` variant should be used to ensure both
256+
control-flow cases are covered.
257+
4. Whenever the `WrappedAccessPaths` are dropped, it's important to add them to the accumulated answer.
256258

257259

258260
Now that we have this partition, computing all the access paths is fairly simple:
259261

260262
1. First, find all datapath expressions. These can be translated into access paths directly.
261-
2. Second, handle all instances of equality between records. For equality between records (`==`) or set containment where the elements are records (`.contains`, `.containsAny`, and `.containsAll`)
263+
2. Second, handle all instances of equality between records.
262264
1. Find all access paths that are children of these operators
263265
1. Following the schema, fully load all fields for the leaf of the access path
264266
3. Finally, handle instances where the ancestors in the entity hierarchy are required. Annotate the left-hand-side of the `in` operator with the `ancestors_required` flag.
265267

266-
##
267268

268269
## SimplifiedEntityLoader API
269270

@@ -308,13 +309,6 @@ pub trait SimpleEntityLoader {
308309
Increasing the complexity of the Cedar API with entity manifests provides new places for users to make mistakes. For example, using an outdated entity manifest can result in unsound entity slices. Another example would be a user writing a buggy implementation of entity loading using the manifest.
309310

310311

311-
### Full Cedar Language Support
312-
313-
The current analysis does not support the full Cedar language (see the **Computing Access Paths** section). With some effort, the implementation could be extended to support all of Cedar by more carefully tracking access paths through different types of Cedar operations. However, it’s unclear just how tricky this will be.
314-
315-
Along a similar note, all Cedar changes in the future will need a corresponding change in the static analysis, making it harder to extend Cedar. For example, any operations that apply to records will need careful consideration.
316-
317-
318312
### Supporting Partial Loading of Sets
319313

320314
As written, entity manifests in this RFC do not support loading only parts of a Cedar Set, or only some of the ancestors in the entity hierarchy. This is because sets are loaded on the leaves of the access trie, with no way to specify which elements are requested.

0 commit comments

Comments
 (0)