Zanzana: handle service accounts (#97123)

* add service account to the schema

* sync managed permissions for service accounts

* sync SA basic roles

* sync SA roles

* Fix endless loop in reconciler while read openfga
This commit is contained in:
Alexander Zobnin 2024-11-28 10:41:30 +01:00 committed by GitHub
parent feecd30687
commit c8caf787d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 90 additions and 68 deletions

View File

@ -115,7 +115,7 @@ func folderTreeCollector(store db.DB) legacyTupleCollector {
func managedPermissionsCollector(store db.DB, kind string) legacyTupleCollector {
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
query := `
SELECT u.uid as user_uid, t.uid as team_uid, p.action, p.kind, p.identifier, r.org_id, br.role as basic_role_name
SELECT u.uid as user_uid, u.is_service_account as is_service_account, t.uid as team_uid, p.action, p.kind, p.identifier, r.org_id, br.role as basic_role_name
FROM permission p
INNER JOIN role r ON p.role_id = r.id
LEFT JOIN user_role ur ON r.id = ur.role_id
@ -132,6 +132,7 @@ func managedPermissionsCollector(store db.DB, kind string) legacyTupleCollector
Kind string
Identifier string
UserUID string `xorm:"user_uid"`
IsServiceAccount bool `xorm:"is_service_account"`
TeamUID string `xorm:"team_uid"`
BasicRoleName string `xorm:"basic_role_name"`
}
@ -149,7 +150,9 @@ func managedPermissionsCollector(store db.DB, kind string) legacyTupleCollector
for _, p := range permissions {
var subject string
if len(p.UserUID) > 0 {
if len(p.UserUID) > 0 && p.IsServiceAccount {
subject = zanzana.NewTupleEntry(zanzana.TypeServiceAccount, p.UserUID, "")
} else if len(p.UserUID) > 0 {
subject = zanzana.NewTupleEntry(zanzana.TypeUser, p.UserUID, "")
} else if len(p.TeamUID) > 0 {
subject = zanzana.NewTupleEntry(zanzana.TypeTeam, p.TeamUID, zanzana.RelationTeamMember)
@ -198,15 +201,18 @@ func tupleStringWithoutCondition(tuple *openfgav1.TupleKey) string {
func basicRoleBindingsCollector(store db.DB) legacyTupleCollector {
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
query := `
SELECT ou.org_id, u.uid as user_uid, ou.role as org_role
SELECT
ou.org_id, u.uid as user_uid,
u.is_service_account as is_service_account,
ou.role as org_role
FROM org_user ou
LEFT JOIN ` + store.GetDialect().Quote("user") + ` u ON u.id = ou.user_id
WHERE ou.org_id = ?
AND NOT u.is_service_account
`
// FIXME: handle service admin role
type Binding struct {
UserUID string `xorm:"user_uid"`
IsServiceAccount bool `xorm:"is_service_account"`
OrgRole string `xorm:"org_role"`
}
@ -222,8 +228,13 @@ func basicRoleBindingsCollector(store db.DB) legacyTupleCollector {
tuples := make(map[string]map[string]*openfgav1.TupleKey)
for _, b := range bindings {
userType := zanzana.TypeUser
if b.IsServiceAccount {
userType = zanzana.TypeServiceAccount
}
tuple := &openfgav1.TupleKey{
User: zanzana.NewTupleEntry(zanzana.TypeUser, b.UserUID, ""),
User: zanzana.NewTupleEntry(userType, b.UserUID, ""),
Relation: zanzana.RelationAssignee,
Object: zanzana.NewTupleEntry(zanzana.TypeRole, zanzana.TranslateBasicRole(b.OrgRole), ""),
}
@ -286,7 +297,7 @@ func teamRoleBindingsCollector(store db.DB) legacyTupleCollector {
func userRoleBindingsCollector(store db.DB) legacyTupleCollector {
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
query := `
SELECT u.uid AS user_uid, r.uid AS role_uid
SELECT u.uid AS user_uid, u.is_service_account as is_service_account, r.uid AS role_uid
FROM user_role ur
INNER JOIN ` + store.GetDialect().Quote("user") + ` u ON ur.user_id = u.id
INNER JOIN role r ON ur.role_id = r.id
@ -295,6 +306,7 @@ func userRoleBindingsCollector(store db.DB) legacyTupleCollector {
`
type Binding struct {
UserUID string `xorm:"user_uid"`
IsServiceAccount bool `xorm:"is_service_account"`
RoleUID string `xorm:"role_uid"`
}
@ -310,8 +322,13 @@ func userRoleBindingsCollector(store db.DB) legacyTupleCollector {
tuples := make(map[string]map[string]*openfgav1.TupleKey)
for _, b := range bindings {
userType := zanzana.TypeUser
if b.IsServiceAccount {
userType = zanzana.TypeServiceAccount
}
tuple := &openfgav1.TupleKey{
User: zanzana.NewTupleEntry(zanzana.TypeUser, b.UserUID, ""),
User: zanzana.NewTupleEntry(userType, b.UserUID, ""),
Relation: zanzana.RelationAssignee,
Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""),
}
@ -397,6 +414,7 @@ func zanzanaCollector(relations []string) zanzanaTupleCollector {
for c != "" {
res, err := client.Read(ctx, &authzextv1.ReadRequest{
ContinuationToken: c,
Namespace: namespace,
TupleKey: &authzextv1.ReadRequestTupleKey{
Object: object,

View File

@ -11,6 +11,7 @@ import (
const (
TypeUser string = "user"
TypeServiceAccount string = "service-account"
TypeTeam string = "team"
TypeRole string = "role"
TypeFolder string = "folder"

View File

@ -2,28 +2,30 @@ module core
type namespace
relations
define view: [user, team#member, role#assignee] or edit
define edit: [user, team#member, role#assignee] or admin
define admin: [user, team#member, role#assignee]
define view: [user, service-account, team#member, role#assignee] or edit
define edit: [user, service-account, team#member, role#assignee] or admin
define admin: [user, service-account, team#member, role#assignee]
define read: [user, team#member, role#assignee] or view
define create: [user, team#member, role#assignee] or edit
define write: [user, team#member, role#assignee] or edit
define delete: [user, team#member, role#assignee] or edit
define permissions_read: [user, team#member, role#assignee] or admin
define permissions_write: [user, team#member, role#assignee] or admin
define read: [user, service-account, team#member, role#assignee] or view
define create: [user, service-account, team#member, role#assignee] or edit
define write: [user, service-account, team#member, role#assignee] or edit
define delete: [user, service-account, team#member, role#assignee] or edit
define permissions_read: [user, service-account, team#member, role#assignee] or admin
define permissions_write: [user, service-account, team#member, role#assignee] or admin
type user
type service-account
type role
relations
define assignee: [user, team#member, role#assignee]
define assignee: [user, service-account, team#member, role#assignee]
type team
relations
# Action sets
define admin: [user]
define member: [user] or admin
define admin: [user, service-account]
define member: [user, service-account] or admin
define read: [role#assignee] or member
define write: [role#assignee] or admin

View File

@ -5,13 +5,13 @@ type folder
define parent: [folder]
# Action sets
define view: [user, team#member, role#assignee] or edit or view from parent
define edit: [user, team#member, role#assignee] or admin or edit from parent
define admin: [user, team#member, role#assignee] or admin from parent
define view: [user, service-account, team#member, role#assignee] or edit or view from parent
define edit: [user, service-account, team#member, role#assignee] or admin or edit from parent
define admin: [user, service-account, team#member, role#assignee] or admin from parent
define read: [user, team#member, role#assignee] or view or read from parent
define create: [user, team#member, role#assignee] or edit or create from parent
define write: [user, team#member, role#assignee] or edit or write from parent
define delete: [user, team#member, role#assignee] or edit or delete from parent
define permissions_read: [user, team#member, role#assignee] or admin or permissions_read from parent
define permissions_write: [user, team#member, role#assignee] or admin or permissions_write from parent
define read: [user, service-account, team#member, role#assignee] or view or read from parent
define create: [user, service-account, team#member, role#assignee] or edit or create from parent
define write: [user, service-account, team#member, role#assignee] or edit or write from parent
define delete: [user, service-account, team#member, role#assignee] or edit or delete from parent
define permissions_read: [user, service-account, team#member, role#assignee] or admin or permissions_read from parent
define permissions_write: [user, service-account, team#member, role#assignee] or admin or permissions_write from parent

View File

@ -2,28 +2,28 @@ module resource
extend type folder
relations
define resource_view: [user, team#member, role#assignee] or resource_edit or resource_view from parent
define resource_edit: [user, team#member, role#assignee] or resource_admin or resource_edit from parent
define resource_admin: [user, team#member, role#assignee] or resource_admin from parent
define resource_view: [user, service-account, team#member, role#assignee] or resource_edit or resource_view from parent
define resource_edit: [user, service-account, team#member, role#assignee] or resource_admin or resource_edit from parent
define resource_admin: [user, service-account, team#member, role#assignee] or resource_admin from parent
define resource_read: [user with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_view or resource_read from parent
define resource_create: [user with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_edit or resource_create from parent
define resource_write: [user with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_edit or resource_write from parent
define resource_delete: [user with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_edit or resource_delete from parent
define resource_permissions_read: [user with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_admin or resource_permissions_read from parent
define resource_permissions_write: [user with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_admin or resource_permissions_write from parent
define resource_read: [user with folder_group_filter, service-account with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_view or resource_read from parent
define resource_create: [user with folder_group_filter, service-account with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_edit or resource_create from parent
define resource_write: [user with folder_group_filter, service-account with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_edit or resource_write from parent
define resource_delete: [user with folder_group_filter, service-account with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_edit or resource_delete from parent
define resource_permissions_read: [user with folder_group_filter, service-account with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_admin or resource_permissions_read from parent
define resource_permissions_write: [user with folder_group_filter, service-account with folder_group_filter, team#member with folder_group_filter, role#assignee with folder_group_filter] or resource_admin or resource_permissions_write from parent
type resource
relations
define view: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or edit
define edit: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or admin
define admin: [user with group_filter, team#member with group_filter, role#assignee with group_filter]
define view: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or edit
define edit: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or admin
define admin: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter]
define read: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or view
define write: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or edit
define delete: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or edit
define permissions_read: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or admin
define permissions_write: [user with group_filter, team#member with group_filter, role#assignee with group_filter] or admin
define read: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or view
define write: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or edit
define delete: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or edit
define permissions_read: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or admin
define permissions_write: [user with group_filter, service-account with group_filter, team#member with group_filter, role#assignee with group_filter] or admin
condition group_filter(requested_group: string, group_resource: string) {
requested_group == group_resource

View File

@ -12,6 +12,7 @@ import (
const (
TypeUser = common.TypeUser
TypeServiceAccount = common.TypeServiceAccount
TypeTeam = common.TypeTeam
TypeRole = common.TypeRole
TypeFolder = common.TypeFolder