Skip to content

Commit

Permalink
feat: allow wildcard on subject.people
Browse files Browse the repository at this point in the history
* allow specifying the subject group directly
  • Loading branch information
adityathebe committed Feb 4, 2025
1 parent e94c0b7 commit 3a91fb2
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 18 deletions.
31 changes: 15 additions & 16 deletions api/v1/permission_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,17 @@ func (t PermissionSubjectSelector) Find(ctx context.Context, table string) (stri

case "notifications":
splits := strings.Split(string(t), "/")
switch len(splits) {
case 1:
return string(t), models.PermissionSubjectTypeGroup, nil // assume it's the group name

case 2:
namespace, name := splits[0], splits[1]
var id string
err := ctx.DB().Select("id").Table(table).
Where("namespace = ?", namespace).
Where("name = ?", name).
Find(&id).Error
return id, models.PermissionSubjectTypeNotification, err
if len(splits) != 2 {
return "", "", fmt.Errorf("%s is not a valid notification subject. must be <namespace>/<name>", t)
}

default:
return "", "", fmt.Errorf("unknown table: %v", table)
namespace, name := splits[0], splits[1]
var id string
err := ctx.DB().Select("id").Table(table).
Where("namespace = ?", namespace).
Where("name = ?", name).
Find(&id).Error
return id, models.PermissionSubjectTypeNotification, err
}

return "", "", nil
Expand All @@ -75,11 +70,12 @@ type PermissionSubject struct {
Person PermissionSubjectSelector `json:"person,omitempty"`
Team PermissionSubjectSelector `json:"team,omitempty"`
Notification PermissionSubjectSelector `json:"notification,omitempty"`
Group PermissionSubjectSelector `json:"group,omitempty"`
}

func (t *PermissionSubject) Validate() error {
if t.Person == "" && t.Team == "" && t.Notification == "" {
return errors.New("subject is empty: one of permission, team or notification is required")
if t.Person == "" && t.Team == "" && t.Notification == "" && t.Group == "" {
return errors.New("subject is empty: one of person, team, notification or a group is required")
}

return nil
Expand All @@ -99,6 +95,9 @@ func (t *PermissionSubject) Populate(ctx context.Context) (string, models.Permis
if t.Notification != "" {
return t.Notification.Find(ctx, "notifications")
}
if t.Group != "" {
return string(t.Group), models.PermissionSubjectTypeGroup, nil
}

return "", "", errors.New("subject not found")
}
Expand Down
8 changes: 8 additions & 0 deletions config/crds/mission-control.flanksource.com_permissions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ spec:
description: Subject defines the entity (e.g., user, group) to which
the permission applies.
properties:
group:
description: |-
Subject of the permission.
Can be
- a permission group name
- id of a resource
- <namespace>/<name> of a resource
type: string
notification:
description: |-
Subject of the permission.
Expand Down
3 changes: 3 additions & 0 deletions config/schemas/permission.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@
},
"notification": {
"type": "string"
},
"group": {
"type": "string"
}
},
"additionalProperties": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ metadata:
spec:
description: allow config notifications to run playbook
subject:
notification: config-notifications
group: config-notifications
actions:
- playbook:run
- playbook:approve
Expand Down
13 changes: 12 additions & 1 deletion rbac/adapter/permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,18 @@ func (a *PermissionAdapter) permissionGroupToCasbinRule(permission models.Permis

if len(subject.People) > 0 {
var personIDs []string
if err := a.db.Select("id").Model(&models.Person{}).Where("email IN ? OR name IN ?", subject.People, subject.People).Find(&personIDs).Error; err != nil {

query := a.db.Select("id").Model(&models.Person{}).
Where("deleted_at IS NULL").
Where("type IS DISTINCT FROM 'agent'").
Where("email IS NOT NULL") // Excludes system user

wildcard := len(subject.People) == 1 && subject.People[0] == "*"
if !wildcard {
query.Where("email IN ? OR name IN ?", subject.People, subject.People)
}

if err := query.Find(&personIDs).Error; err != nil {
return nil, err
}

Expand Down

0 comments on commit 3a91fb2

Please sign in to comment.