Repository navigation
ateapi: [Part 2] Runtime Authorization check for Actor and ActorTemplate CRUD - #1980
Conversation
4a9ff16 to
ded45ff
Compare
c459548 to
ad5a0d9
Compare
Actor and ActorTemplate RPCs were not covered by the authz interceptor, so with --experimental-enable-authz set, callers could read and modify them in any atespace. The registry now maps each RPC to a list of checks, all of which must pass. CreateActor needs can_create_actor on the atespace and UpdateActor needs can_update on the actor; both also need can_use on the referenced actor template, which may live in another atespace. Get and Delete check the resource, and List checks the atespace, or global:root when the atespace is empty. Actors and templates are identified as actor:<atespace>/<name> and actor_template:<atespace>/<name>. Their parent atespace is derived from the ID and sent as contextual tuples, so no tuples are written on create or delete. '/' is escaped in each component so every ID names exactly one resource.
The check extractors used to leave out a check whose atespace or name was missing and rely on the handler to reject the request. For UpdateActor, whose request validation does not descend into the actor, that left the template check to validation run deep inside the store transaction. Names OpenFGA cannot accept in an object ID also surfaced as Internal. Extractors now require every identifier a check needs to be present and a valid resource name, and return InvalidArgument with the field path otherwise, so no check is skipped and OpenFGA never sees a malformed ID. The interceptor authenticates before extracting, so unauthenticated callers still get Unauthenticated.
Actor and actor template checks reach global:root only through the contextual actor -> atespace -> global:root links. Cover a global owner and a bootstrap owner, which has no stored tuples, on get, update, and delete, and a global viewer being denied the writes.
The actor_template relation that gates running actors from a template is now can_use_template, so the permission name says what is being used.
0f54ab7 to
5d3e2ea
Compare
| // tuples in PostgreSQL. | ||
| // | ||
| // Why contextual tuples are used instead of storing `parent_global` in the database: | ||
| // Why contextual tuples are used instead of storing parent links in the database: |
There was a problem hiding this comment.
(This is a longer-term comment we should think about, but doesn't block submitting this PR).
Why not do everything with contextual tuples? Why do we need to to use OpenFGA's relation table at all, if all of the information in it is redundant with information stored in the Substrate tables.
I think the answer (if there is one) is that OpenFGA should be doing its graph search during retrieval from the relation table, rather than loading everything into memory and doing the graph search there. So are we harming the ability for that to happen by using contextual tuples for things that OpenFGA expects to be concrete in the relation table?)
(My mental model of contextual tuples is that they are for things that are inherently request-scoped, for example, the fact that a user authenticated with a client cert or a JWT, or the geolocation of their calling IP)
There was a problem hiding this comment.
+1,
May be I am over abusing contextual tuples. Let me create a task to think through if we should store the structural links during creation of the resource.
There was a problem hiding this comment.
Working on #1563
Fixes #1699
Adds OpenFGA authorization checks for
ActorandActorTemplateCRUD RPCs, enforced when--experimental-enable-authzis set. AccessPolicy RPCs are still always enforced.Checks
CreateActorTemplatecan_create_actor_templateonatespaceGet/DeleteActorTemplatecan_get/can_deleteonactor_templateListActorTemplatescan_list_actor_templatesonatespace(orglobal:root)CreateActorcan_create_actoronatespace+can_use_templateon templateUpdateActorcan_updateonactor+can_use_templateon templateGet/DeleteActorcan_get/can_deleteonactorListActorscan_list_actorsonatespace(orglobal:root)Notes
InvalidArgumentand the field path. No check is skipped, so this does not depend on handler validation.actor/actor_template→atespace→global:root) are passed as contextual tuples, so creating or deleting a resource writes no tuples. Global owners, stored or bootstrap, reach actors and templates through these links.UpdateActoralways checkscan_use_templateon the template. Checking only when the template changes is left for a follow-up.Testing