diff options
impl authZ write and check (depends on spicedb for now)
Diffstat (limited to 'crates/secd/proto/authzed/api/v1/permission_service.proto')
| -rw-r--r-- | crates/secd/proto/authzed/api/v1/permission_service.proto | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/crates/secd/proto/authzed/api/v1/permission_service.proto b/crates/secd/proto/authzed/api/v1/permission_service.proto new file mode 100644 index 0000000..859d0d0 --- /dev/null +++ b/crates/secd/proto/authzed/api/v1/permission_service.proto @@ -0,0 +1,438 @@ +syntax = "proto3"; +package authzed.api.v1; + +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_package = "com.authzed.api.v1"; + +import "google/protobuf/struct.proto"; +import "google/api/annotations.proto"; +import "validate/validate.proto"; + +import "authzed/api/v1/core.proto"; + +// PermissionsService implements a set of RPCs that perform operations on +// relationships and permissions. +service PermissionsService { + // ReadRelationships reads a set of the relationships matching one or more + // filters. + rpc ReadRelationships(ReadRelationshipsRequest) + returns (stream ReadRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/read" + body: "*" + }; + } + + // WriteRelationships atomically writes and/or deletes a set of specified + // relationships. An optional set of preconditions can be provided that must + // be satisfied for the operation to commit. + rpc WriteRelationships(WriteRelationshipsRequest) + returns (WriteRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/write" + body: "*" + }; + } + + // DeleteRelationships atomically bulk deletes all relationships matching the + // provided filter. If no relationships match, none will be deleted and the + // operation will succeed. An optional set of preconditions can be provided that must + // be satisfied for the operation to commit. + rpc DeleteRelationships(DeleteRelationshipsRequest) + returns (DeleteRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/delete" + body: "*" + }; + } + + // CheckPermission determines for a given resource whether a subject computes + // to having a permission or is a direct member of a particular relation. + rpc CheckPermission(CheckPermissionRequest) + returns (CheckPermissionResponse) { + option (google.api.http) = { + post: "/v1/permissions/check" + body: "*" + }; + } + + // ExpandPermissionTree reveals the graph structure for a resource's + // permission or relation. This RPC does not recurse infinitely deep and may + // require multiple calls to fully unnest a deeply nested graph. + rpc ExpandPermissionTree(ExpandPermissionTreeRequest) + returns (ExpandPermissionTreeResponse) { + option (google.api.http) = { + post: "/v1/permissions/expand" + body: "*" + }; + } + + // LookupResources returns all the resources of a given type that a subject + // can access whether via a computed permission or relation membership. + rpc LookupResources(LookupResourcesRequest) + returns (stream LookupResourcesResponse) { + option (google.api.http) = { + post: "/v1/permissions/resources" + body: "*" + }; + } + + // LookupSubjects returns all the subjects of a given type that + // have access whether via a computed permission or relation membership. + rpc LookupSubjects(LookupSubjectsRequest) + returns (stream LookupSubjectsResponse) { + option (google.api.http) = { + post: "/v1/permissions/subjects" + body: "*" + }; + } +} + +// Consistency will define how a request is handled by the backend. +// By defining a consistency requirement, and a token at which those +// requirements should be applied, where applicable. +message Consistency { + oneof requirement { + option (validate.required) = true; + + // minimize_latency indicates that the latency for the call should be + // minimized by having the system select the fastest snapshot available. + bool minimize_latency = 1 [ (validate.rules).bool.const = true ]; + + // at_least_as_fresh indicates that all data used in the API call must be + // *at least as fresh* as that found in the ZedToken; more recent data might + // be used if available or faster. + ZedToken at_least_as_fresh = 2; + + // at_exact_snapshot indicates that all data used in the API call must be + // *at the given* snapshot in time; if the snapshot is no longer available, + // an error will be returned to the caller. + ZedToken at_exact_snapshot = 3; + + // fully_consistent indicates that all data used in the API call *must* be + // at the most recent snapshot found. + // + // NOTE: using this method can be *quite slow*, so unless there is a need to + // do so, it is recommended to use `at_least_as_fresh` with a stored + // ZedToken. + bool fully_consistent = 4 [ (validate.rules).bool.const = true ]; + } +} + +// RelationshipFilter is a collection of filters which when applied to a +// relationship will return relationships that have exactly matching fields. +// +// resource_type is required. All other fields are optional and if left +// unspecified will not filter relationships. +message RelationshipFilter { + string resource_type = 1 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$", + max_bytes : 128, + } ]; + + string optional_resource_id = 2 [ (validate.rules).string = { + pattern : "^([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})?$", + max_bytes : 128, + } ]; + + string optional_relation = 3 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", + max_bytes : 64, + } ]; + + SubjectFilter optional_subject_filter = 4; +} + +// SubjectFilter specifies a filter on the subject of a relationship. +// +// subject_type is required and all other fields are optional, and will not +// impose any additional requirements if left unspecified. +message SubjectFilter { + message RelationFilter { + string relation = 1 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", + max_bytes : 64, + } ]; + } + + string subject_type = 1 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$", + max_bytes : 128, + } ]; + + string optional_subject_id = 2 [ (validate.rules).string = { + pattern : "^(([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})|\\*)?$", + max_bytes : 128, + } ]; + + RelationFilter optional_relation = 3; +} + +// ReadRelationshipsRequest specifies one or more filters used to read matching +// relationships within the system. +message ReadRelationshipsRequest { + Consistency consistency = 1; + RelationshipFilter relationship_filter = 2 + [ (validate.rules).message.required = true ]; +} + +// ReadRelationshipsResponse contains a Relationship found that matches the +// specified relationship filter(s). A instance of this response message will +// be streamed to the client for each relationship found. +message ReadRelationshipsResponse { + ZedToken read_at = 1 [ (validate.rules).message.required = true ]; + Relationship relationship = 2 [ (validate.rules).message.required = true ]; +} + +// Precondition specifies how and the existence or absence of certain +// relationships as expressed through the accompanying filter should affect +// whether or not the operation proceeds. +// +// MUST_NOT_MATCH will fail the parent request if any relationships match the +// relationships filter. +// MUST_MATCH will fail the parent request if there are no +// relationships that match the filter. +message Precondition { + enum Operation { + OPERATION_UNSPECIFIED = 0; + OPERATION_MUST_NOT_MATCH = 1; + OPERATION_MUST_MATCH = 2; + } + + Operation operation = 1 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + RelationshipFilter filter = 2 [ (validate.rules).message.required = true ]; +} + +// WriteRelationshipsRequest contains a list of Relationship mutations that +// should be applied to the service. If the optional_preconditions parameter +// is included, all of the specified preconditions must also be satisfied before +// the write will be committed. +message WriteRelationshipsRequest { + repeated RelationshipUpdate updates = 1 + [ (validate.rules).repeated .items.message.required = true ]; + + repeated Precondition optional_preconditions = 2 + [ (validate.rules).repeated .items.message.required = + true ]; // To be bounded by configuration +} + +message WriteRelationshipsResponse { ZedToken written_at = 1; } + +// DeleteRelationshipsRequest specifies which Relationships should be deleted, +// requesting the delete of *ALL* relationships that match the specified +// filters. If the optional_preconditions parameter is included, all of the +// specified preconditions must also be satisfied before the delete will be +// executed. +message DeleteRelationshipsRequest { + RelationshipFilter relationship_filter = 1 + [ (validate.rules).message.required = true ]; + + repeated Precondition optional_preconditions = 2 + [ (validate.rules).repeated .items.message.required = + true ]; // To be bounded by configuration +} + +message DeleteRelationshipsResponse { ZedToken deleted_at = 1; } + +// CheckPermissionRequest issues a check on whether a subject has a permission +// or is a member of a relation, on a specific resource. +message CheckPermissionRequest { + Consistency consistency = 1; + + // resource is the resource on which to check the permission or relation. + ObjectReference resource = 2 [ (validate.rules).message.required = true ]; + + // permission is the name of the permission (or relation) on which to execute + // the check. + string permission = 3 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", + max_bytes : 64, + } ]; + + // subject is the subject that will be checked for the permission or relation. + SubjectReference subject = 4 [ (validate.rules).message.required = true ]; + + /** context consists of named values that are injected into the caveat evaluation context **/ + google.protobuf.Struct context = 5 [ (validate.rules).message.required = false ]; +} + +message CheckPermissionResponse { + enum Permissionship { + PERMISSIONSHIP_UNSPECIFIED = 0; + PERMISSIONSHIP_NO_PERMISSION = 1; + PERMISSIONSHIP_HAS_PERMISSION = 2; + PERMISSIONSHIP_CONDITIONAL_PERMISSION = 3; + } + + ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; + + // Permissionship communicates whether or not the subject has the requested + // permission or has a relationship with the given resource, over the given + // relation. + // + // This value will be authzed.api.v1.PERMISSIONSHIP_HAS_PERMISSION if the + // requested subject is a member of the computed permission set or there + // exists a relationship with the requested relation from the given resource + // to the given subject. + Permissionship permissionship = 2 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + + // partial_caveat_info holds information of a partially-evaluated caveated response + PartialCaveatInfo partial_caveat_info = 3 [ (validate.rules).message.required = false ]; +} + +// ExpandPermissionTreeRequest returns a tree representing the expansion of all +// relationships found accessible from a permission or relation on a particular +// resource. +// +// ExpandPermissionTreeRequest is typically used to determine the full set of +// subjects with a permission, along with the relationships that grant said +// access. +message ExpandPermissionTreeRequest { + Consistency consistency = 1; + + // resource is the resource over which to run the expansion. + ObjectReference resource = 2 [ (validate.rules).message.required = true ]; + + // permission is the name of the permission or relation over which to run the + // expansion for the resource. + string permission = 3 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", + max_bytes : 64, + } ]; +} + +message ExpandPermissionTreeResponse { + ZedToken expanded_at = 1; + + // tree_root is a tree structure whose leaf nodes are subjects, and + // intermediate nodes represent the various operations (union, intersection, + // exclusion) to reach those subjects. + PermissionRelationshipTree tree_root = 2; +} + +// LookupResourcesRequest performs a lookup of all resources of a particular +// kind on which the subject has the specified permission or the relation in +// which the subject exists, streaming back the IDs of those resources. +message LookupResourcesRequest { + Consistency consistency = 1; + + // resource_object_type is the type of resource object for which the IDs will + // be returned. + string resource_object_type = 2 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$", + max_bytes : 128, + } ]; + + // permission is the name of the permission or relation for which the subject + // must Check. + string permission = 3 [ (validate.rules).string = { + pattern : "^[a-z][a-z0-9_]{1,62}[a-z0-9]$", + max_bytes : 64, + } ]; + + // subject is the subject with access to the resources. + SubjectReference subject = 4 [ (validate.rules).message.required = true ]; + + /** context consists of named values that are injected into the caveat evaluation context **/ + google.protobuf.Struct context = 5 [ (validate.rules).message.required = false ]; +} + +// LookupPermissionship represents whether a Lookup response was partially evaluated or not +enum LookupPermissionship { + LOOKUP_PERMISSIONSHIP_UNSPECIFIED = 0; + LOOKUP_PERMISSIONSHIP_HAS_PERMISSION = 1; + LOOKUP_PERMISSIONSHIP_CONDITIONAL_PERMISSION = 2; +} + +// LookupResourcesResponse contains a single matching resource object ID for the +// requested object type, permission, and subject. +message LookupResourcesResponse { + ZedToken looked_up_at = 1; + string resource_object_id = 2; + + // permissionship indicates whether the response was partially evaluated or not + LookupPermissionship permissionship = 3 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + + // partial_caveat_info holds information of a partially-evaluated caveated response + PartialCaveatInfo partial_caveat_info = 4 [ (validate.rules).message.required = false ]; +} + +// LookupSubjectsRequest performs a lookup of all subjects of a particular +// kind for which the subject has the specified permission or the relation in +// which the subject exists, streaming back the IDs of those subjects. +message LookupSubjectsRequest { + Consistency consistency = 1; + + // resource is the resource for which all matching subjects for the permission + // or relation will be returned. + ObjectReference resource = 2 [ (validate.rules).message.required = true ]; + + // permission is the name of the permission (or relation) for which to find + // the subjects. + string permission = 3 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", + max_bytes : 64, + } ]; + + // subject_object_type is the type of subject object for which the IDs will + // be returned. + string subject_object_type = 4 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$", + max_bytes : 128, + } ]; + + // optional_subject_relation is the optional relation for the subject. + string optional_subject_relation = 5 [ (validate.rules).string = { + pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", + max_bytes : 64, + } ]; + + /** context consists of named values that are injected into the caveat evaluation context **/ + google.protobuf.Struct context = 6 [ (validate.rules).message.required = false ]; +} + +// LookupSubjectsResponse contains a single matching subject object ID for the +// requested subject object type on the permission or relation. +message LookupSubjectsResponse { + ZedToken looked_up_at = 1; + + // subject_object_id is the Object ID of the subject found. May be a `*` if + // a wildcard was found. + // deprecated: use `subject` + string subject_object_id = 2 [deprecated = true]; + + // excluded_subject_ids are the Object IDs of the subjects excluded. This list + // will only contain object IDs if `subject_object_id` is a wildcard (`*`) and + // will only be populated if exclusions exist from the wildcard. + // deprecated: use `excluded_subjects` + repeated string excluded_subject_ids = 3 [deprecated = true]; + + // permissionship indicates whether the response was partially evaluated or not + // deprecated: use `subject.permissionship` + LookupPermissionship permissionship = 4 [ deprecated = true, (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + + // partial_caveat_info holds information of a partially-evaluated caveated response + // deprecated: use `subject.partial_caveat_info` + PartialCaveatInfo partial_caveat_info = 5 [ deprecated = true, (validate.rules).message.required = false ]; + + // subject is the subject found, along with its permissionship. + ResolvedSubject subject = 6; + + // excluded_subjects are the subjects excluded. This list + // will only contain subjects if `subject.subject_object_id` is a wildcard (`*`) and + // will only be populated if exclusions exist from the wildcard. + repeated ResolvedSubject excluded_subjects = 7; +} + +// ResolvedSubject is a single subject resolved within LookupSubjects. +message ResolvedSubject { + // subject_object_id is the Object ID of the subject found. May be a `*` if + // a wildcard was found. + string subject_object_id = 1; + + // permissionship indicates whether the response was partially evaluated or not + LookupPermissionship permissionship = 2 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + + // partial_caveat_info holds information of a partially-evaluated caveated response + PartialCaveatInfo partial_caveat_info = 3 [ (validate.rules).message.required = false ]; +}
\ No newline at end of file |
