mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 03:02:44 +08:00

* replace xorm.io/xorm imports * replace xorm from other go.mod files * clean up workspace * nolint does not make sense anymore as it is not a module * try if nolint directive helps * use nolint:all for xorm * add more nolints * try to skip xorm in linter config * exclude xorm differently * retrigger ci
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
package accesscontrol
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/grafana/grafana/pkg/util/xorm"
|
|
|
|
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
|
)
|
|
|
|
const (
|
|
orphanedServiceAccountsPermissions = "delete orphaned service account permissions"
|
|
)
|
|
|
|
func AddOrphanedMigrations(mg *migrator.Migrator) {
|
|
mg.AddMigration(orphanedServiceAccountsPermissions, &orphanedServiceAccountPermissions{})
|
|
}
|
|
|
|
var _ migrator.CodeMigration = new(alertingScopeRemovalMigrator)
|
|
|
|
type orphanedServiceAccountPermissions struct {
|
|
migrator.MigrationBase
|
|
}
|
|
|
|
func (m *orphanedServiceAccountPermissions) SQL(dialect migrator.Dialect) string {
|
|
return CodeMigrationSQL
|
|
}
|
|
|
|
func (m *orphanedServiceAccountPermissions) Exec(sess *xorm.Session, mg *migrator.Migrator) error {
|
|
var idents []string
|
|
|
|
// find all permissions that are scopes directly to a service account
|
|
err := sess.SQL("SELECT DISTINCT p.identifier FROM permission AS p WHERE p.kind = 'serviceaccounts' AND NOT p.identifier = '*'").Find(&idents)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to fetch permissinos scoped to service accounts: %w", err)
|
|
}
|
|
|
|
ids := make([]int64, 0, len(idents))
|
|
for _, id := range idents {
|
|
id, err := strconv.ParseInt(id, 10, 64)
|
|
if err == nil {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
|
|
if len(ids) == 0 {
|
|
return nil
|
|
}
|
|
|
|
return batch(len(ids), batchSize, func(start, end int) error {
|
|
return m.exec(sess, mg, ids[start:end])
|
|
})
|
|
}
|
|
|
|
func (m *orphanedServiceAccountPermissions) exec(sess *xorm.Session, mg *migrator.Migrator, ids []int64) error {
|
|
// get all service accounts from batch
|
|
raw := "SELECT u.id FROM " + mg.Dialect.Quote("user") + " AS u WHERE u.is_service_account AND u.id IN(?" + strings.Repeat(",?", len(ids)-1) + ")"
|
|
args := make([]any, 0, len(ids))
|
|
for _, id := range ids {
|
|
args = append(args, id)
|
|
}
|
|
|
|
var existingIDs []int64
|
|
err := sess.SQL(raw, args...).Find(&existingIDs)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to fetch existing service accounts: %w", err)
|
|
}
|
|
|
|
existing := make(map[int64]struct{}, len(existingIDs))
|
|
for _, id := range existingIDs {
|
|
existing[id] = struct{}{}
|
|
}
|
|
|
|
// filter out orphaned permissions
|
|
var orphaned []string
|
|
for _, id := range ids {
|
|
if _, ok := existing[id]; !ok {
|
|
orphaned = append(orphaned, strconv.FormatInt(id, 10))
|
|
}
|
|
}
|
|
|
|
if len(orphaned) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// delete all orphaned permissions
|
|
rawDelete := "DELETE FROM permission WHERE kind = 'serviceaccounts' AND identifier IN(?" + strings.Repeat(",?", len(orphaned)-1) + ")"
|
|
deleteArgs := make([]any, 0, len(orphaned)+1)
|
|
deleteArgs = append(deleteArgs, rawDelete)
|
|
for _, id := range orphaned {
|
|
deleteArgs = append(deleteArgs, id)
|
|
}
|
|
|
|
_, err = sess.Exec(deleteArgs...)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete orphaned service accounts: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|