diff --git a/proto/global_admin.proto b/proto/global_admin.proto index 66ced48..ff5f04a 100644 --- a/proto/global_admin.proto +++ b/proto/global_admin.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +import "permissionrules.proto"; + option go_package = "github.com/momentohq/client-sdk-go;client_sdk_go"; option java_multiple_files = true; option java_package = "grpc.global_admin"; @@ -22,6 +24,9 @@ service GlobalAdmin { rpc RejectInvitation(_RejectInvitationRequest) returns (_RejectInvitationResponse) {} rpc ListInvitationsForAccount(_ListInvitationsForAccountRequest) returns (_ListInvitationsForAccountResponse) {} rpc RevokeInvitation(_RevokeInvitationRequest) returns (_RevokeInvitationResponse) {} + rpc ListRolesForAccount(_ListRolesForAccountRequest) returns (_ListRolesForAccountResponse) {} + rpc SetMemberRole(_SetMemberRoleRequest) returns (_SetMemberRoleResponse) {} + } message _SetAccountNameRequest { @@ -30,7 +35,6 @@ message _SetAccountNameRequest { message _SetAccountNameResponse {} -// No parameters required - we derive identity from the auth header. message _GetAccountsRequest { } @@ -53,6 +57,8 @@ message _GetInvitationsForUserResponse { message _Account { string id = 1; string account_name = 2; + string role_id = 3; + string role_name = 4; } message _GetAccountSessionTokenRequest { @@ -61,18 +67,21 @@ message _GetAccountSessionTokenRequest { message _GetAccountSessionTokenResponse { string account_session_token = 1; + permission_rules.PermissionSet permissions = 2; } // API Key needs to be provided via the "authorization" header. // The Account to add the User to is derived from the API key, which is account-scoped. message _InviteMemberRequest { string user_name = 1; + string role_id = 2; } // This response is for when a Member is invited to the Account, // These are some of the Errors and their corresponding GRPC status codes. // 1. User is already a Member. grpc code = FAILED_PRECONDITION. Metadata: "err" -> "already_a_member". // 2. Account has too many Members. grpc code = RESOURCE_EXHAUSTED. Metadata: "err" -> "max_member_count_exceeded". +// 3. Invalid role. grpc code = INVALID_ARGUMENT. message _InviteMemberResponse { } @@ -100,7 +109,8 @@ message _ListInvitationsForAccountRequest {} message _Invitation { string id = 1; - _Member member = 2; + _Member member = 2; // TODO: deprecate after migrating to new roles + _AccountMember account_member = 3; } message _ListInvitationsForAccountResponse { @@ -144,8 +154,15 @@ message _Member { Role role = 2; } +message _AccountMember { + string user_name = 1; + string role_id = 2; + string role_name = 3; +} + message _ListMembersResponse { - repeated _Member members = 1; + repeated _Member members = 1; // TODO: Deprecate this once we migrate to new roles + repeated _AccountMember account_members = 2; } // API Key needs to be provided via the "authorization" header. @@ -162,3 +179,42 @@ message Endpoint { string domain_name = 2; // domain name for talking to this Endpoint, e.g. `cell-4-us-west-2-1.prod.a.momentohq.com` string region = 3; // AWS region, e.g. `us-west-2` } + +message _ListRolesForAccountRequest { +} + + +enum RoleType { + SYSTEM = 0; + CUSTOM = 1; +} + +message AccountRole { + string role_id = 1; // unique identifier + string role_name = 2; // friendly name + permission_rules.PermissionSet permissions = 3; // permissions associated with the role + RoleType role_type = 4; // system or custom role +} + +// This response is when we list all the roles for an account (system roles + custom roles). +// These are the error cases: +// 1. Account does not exist. grpc code = NOT_FOUND. Metadata: "err" -> "account_not_found". +message _ListRolesForAccountResponse { + repeated AccountRole roles = 1; +} + +message _SetMemberRoleRequest { + string user_name = 1; + string desired_role_id = 2; +} + +// This response is when a Member has their membership status changed successfully. +// These are the error cases: +// 1. User is not a member. grpc code = NOT_FOUND. Metadata: "err" -> "user_is_not_a_member". +// 2. User already has the desired membership status. grpc code = FAILED_PRECONDITION. Metadata: "err" -> "same_role". +// 3. Last Owner cannot be demoted. grpc code = FAILED_PRECONDITION. Metadata: "err" -> "only_owner_cannot_be_removed". +// 4. User does not exist. grpc code = NOT_FOUND. Metadata: "err" -> "user_not_found". +// 5. Account does not exist. grpc code = NOT_FOUND. Metadata: "err" -> "account_not_found". +// 6. Role does not exist. grpc code = NOT_FOUND. Metadata: "err" -> "role_not_found". +message _SetMemberRoleResponse { +} diff --git a/proto/permissionrules.proto b/proto/permissionrules.proto new file mode 100644 index 0000000..4a6a488 --- /dev/null +++ b/proto/permissionrules.proto @@ -0,0 +1,199 @@ +syntax = "proto3"; + +option go_package = "github.com/momentohq/client-sdk-go;client_sdk_go"; +option java_multiple_files = true; +option java_package = "grpc.permission_rules"; +option csharp_namespace = "Momento.Protos.PermissionRules"; + +package permission_rules; + +// This is "Version 2" of permissions in Momento. + +// Some general terminology (exceptions to be noted) +// Read = "access a specific resource without modification" +// List = "access a unspecified set of resources without modification" List is separated from read many. List actions +// cannot predetermine which resources will be accessed. List is always total - it cannot be restricted by a resource +// selector. +// Write = "access a resource or resources with modification" + +// Used for generic "everything" resource selectors. +message All {} + +// Permissions related to global account management APIs +enum AccountManagementPermissions { + // Can only read account information + AccountRead = 0; + // Can take management actions + AccountWrite = 1; + // Can list accounts + AccountList = 2; +} + +// Permissions related to managing authentication resources. +enum AuthManagementPermissions { + // Can only read auth keys/roles metadata. Read does not allow retrieving secrets - that is considered "modification" + AuthRead = 0; + // Can create and manage auth keys/roles + AuthWrite = 1; + // Can list auth keys/roles metadata. List does not allow retrieving secrets - that is considered "modification" + AuthList = 2; +} + +// Permissions related to managing Momento resources (Caches, Stores, Webhooks, etc.) +enum ResourceManagementPermissions { + // Can only read resources + ResourceRead = 0; + // Can create/manage resources + ResourceWrite = 1; + // Can list resources + ResourceList = 2; +} + +enum CacheAPIPermissions { + // Does not apply to individual resources + CacheList = 0; + // Restricts access to apis that read data from caches: No higher level resource description or modification. + CacheRead = 1; + // Restricts access to apis that write to caches: No higher level resource description or modification. + CacheWrite = 2; +} + +// Allows specifying specific caches. +message CacheSelector { + oneof kind { + string cache_name = 1; + } +} + +// Allows specifying specific items within caches. +message CacheItemSelector { + oneof kind { + bytes key = 1; + bytes key_prefix = 2; + } +} + +enum StoreAPIPermissions { + // Does not apply to individual resources + StoreList = 0; + // Restricts access to apis that read data from stores: No higher level resource description or modification. + StoreRead = 1; + // Restricts access to apis that write to stores: No higher level resource description or modification. + StoreWrite = 2; +} + +// Allows specifying specific stores. +message StoreSelector { + oneof kind { + string store_name = 1; + } +} + +// Allows specifying specific items within stores. +message StoreItemSelector { + oneof kind { + bytes key = 1; + bytes key_prefix = 2; + } +} + +// Topic API Restrictions +enum TopicAPIPermissions { + // Does not apply to individual resources + TopicList = 0; + // Restricts access to apis that read data from topics: No higher level resource description or modification. + TopicRead = 1; + // Restricts access to apis that write to topics: No higher level resource description or modification. + TopicWrite = 2; +} + +// Allows specifying specific topics within caches. +message TopicSelector { + oneof kind { + string topic_name = 1; + string topic_name_prefix = 2; + } +} + +message PermissionSet { + oneof kind { + SuperUserPermissions super_user = 1; + ExplicitPermissions explicit = 2; + } +} + +enum SuperUserPermissions { + SuperUser = 0; +} + +message ExplicitPermissions { + repeated Rule rules = 1; +} + +message Rule { + oneof kind { + AccountManagementRule account_management_rule = 1; + AuthManagementRule auth_management_rule = 2; + ResourceManagementRule resource_management_rule = 3; + CacheRule cache_rule = 4; + TopicRule topic_rule = 5; + StoreRule storage_rule = 6; + } + + message AccountManagementRule { + repeated AccountManagementPermissions permissions = 1; + // No resource selectors here - permissions are inherently account-scoped. + } + + message AuthManagementRule { + repeated AuthManagementPermissions permissions = 1; + // No fine-grained resource control yet. + oneof auth_items { + All all_items = 2; + } + } + + message ResourceManagementRule { + repeated ResourceManagementPermissions permissions = 1; + // No fine-grained resource control yet. + oneof resources { + All all_resources = 2; + } + } + + message CacheRule { + repeated CacheAPIPermissions permissions = 1; + oneof cache { + All all_caches = 2; + CacheSelector cache_selector = 3; + } + oneof cache_item { + All all_items = 4; + CacheItemSelector item_selector = 5; + } + } + + message TopicRule { + repeated TopicAPIPermissions permissions = 1; + oneof cache { + All all_caches = 2; + CacheSelector cache_selector = 3; + } + oneof topic { + All all_topics = 4; + TopicSelector topic_selector = 5; + } + } + + message StoreRule { + repeated StoreAPIPermissions permissions = 1; + oneof store { + All all_stores = 2; + StoreSelector store_selector = 3; + } + oneof store_item { + All all_items = 4; + StoreItemSelector item_selector = 5; + } + } +}