Reserve Identifiers for Internal Use
Related issues and PRs
Timeline
- Started: 2024-02-14
- Accepted: 2024-06-10
- Landed: 2024-07-15 on
main
- Released: 2024-09-16 in
cedar-policy
v4.0.0
Note: These statuses are based on the first version of the RFC process.
Summary
This RFC extends the reservation of the __cedar
namespace in schema in RFC24 and
proposes reserving all namespaces and identifiers where the first element is __cedar
,
forbidding their use in Cedar policies, schema, and entity data so that they can be used by future Cedar language features.
Basic example
Under this RFC the names __cedar
, __cedar::Long
, and __cedar::namespace::User
will all become invalid in all contexts.
These would be rejected in a policy
permit(principal == __cedar::User::"alice", actions, resource);
in a schema
namespace __cedar {
entity User;
}
and in entity data
[
{
"uid": { "__entity": {
"type": "__cedar::User",
"id": "alice"
}},
"attrs": {},
"parents": []
}
]
In this entity data example, the __entity
JSON key does not demonstrate the new reserved namespace mechanism.
It is a place were we already assign special significance to some identifiers starting with __
in entity data.
Motivation
In designing RFC24 we found that we needed to disambiguate user defined identifiers from built-in primitive and extension types.
We accomplished this by reserving only the __cedar
namespace inside of schema,
but we anticipate that we may need more reserved namespaces in more contexts in the future.
Detailed design
We will update the namespace grammar to the following to exclude namespaces and identifiers starting with __cedar
.
Path ::= IDENT {'::' TRAILING_NAMESPACE_IDENT}
IDENT ::= INNER_IDENT - '__cedar'
TRAILING_NAMESPACE_IDENT ::= ['_''a'-'z''A'-'Z']['_''a'-'z''A'-'Z''0'-'9']* - RESERVED
RESERVED ::= 'true' | 'false' | 'if' | 'then' | 'else' | 'in' | 'like' | 'has'
This primarily applies to entity types names.
In the case where an entity type isn't qualified with a namespace, the leading identifier is just the entity type, so we would forbid an unqualified type __cedar
.
It also applies anywhere else namespaces may appear, including the top-level namespace
element in a schema file, qualified references to common types in a schema file, and extension function names in policies.
It also applies where a standalone identifier is expected.
For example, an entity attribute could not be __cedar
.
Reserving this single attribute is not own it's own particularly useful, but we may later extend the attribute grammar to accept namespace paths.
Drawbacks
This is a significant breaking change.
Anyone using the __cedar
namespace will need to update their policies, schema, and entity data to use an unreserved namespace.
The nature of this breaking change fortunately allows for migration away from reserved namespaces before the change is released,
and the break will manifest immediately on attempting to parse an affected policy, schema, or entity.
Alternatives
A larger breaking change
We could make a larger breaking change by reserving identifiers starting with __
instead of just __cedar
.
For example, we would additional forbid referencing an entity __tiny_todo::User
.
We don't currently see an immediate need for this more aggressive change, and it increases the likelihood a current user will be affected.
We may also find that consumers of Cedar who expose the policy language to their users want to reserve namespaces for their own use.
They could of course choose a namespace with any leading characters, but they may prefer the uniformity between __cedar::Long
and, for example, __tiny_todo
.
No breaking change
We can avoid a breaking change to Cedar by updating the Grammar to allow for a new identifier that is currently invalid, and then reserve that identifier.
For example, we could reserve $cedar
or cedar$
(other options for characters include %
or !
).
It would would be an error to use this identifier in any way that isn't explicitly permitted by the Cedar spec.
Taking this option would require an update to the schema grammar proposed in RFC24.