4328d25f22
Cluster-secret holder could POST a backup with their own admin key to /api/backup/import, replacing all users — privilege escalation from cluster-auth to admin. Also, Kuma imports produced zero users but ImportWipe unconditionally deleted the users table — locking out all accounts until restart reseeded UPTOP_ADMIN_KEY. - Server handlers strip data.Users (set nil) before calling ImportData - ImportData only wipes+replaces users when data.Users != nil - New ImportWipeUsers dialect method separates user wipe from data wipe - CLI restore (main.go) unchanged — full import still replaces users
44 lines
807 B
Go
44 lines
807 B
Go
package store
|
|
|
|
import (
|
|
"database/sql"
|
|
"strconv"
|
|
)
|
|
|
|
type Migration struct {
|
|
Version int
|
|
SQL string
|
|
}
|
|
|
|
type Dialect interface {
|
|
DriverName() string
|
|
CreateTablesSQL() []string
|
|
Migrations() []Migration
|
|
BaselineVersion() int
|
|
BoolFalse() string
|
|
ResetSequenceOnEmpty(db *sql.DB, table string)
|
|
ImportWipe(tx *sql.Tx)
|
|
ImportWipeUsers(tx *sql.Tx)
|
|
ImportResetSequences(tx *sql.Tx)
|
|
UpsertNodeSQL() string
|
|
UpsertAlertHealthSQL() string
|
|
}
|
|
|
|
func rewritePlaceholders(query string, dollarStyle bool) string {
|
|
if !dollarStyle {
|
|
return query
|
|
}
|
|
buf := make([]byte, 0, len(query)+32)
|
|
n := 0
|
|
for i := 0; i < len(query); i++ {
|
|
if query[i] == '?' {
|
|
n++
|
|
buf = append(buf, '$')
|
|
buf = append(buf, []byte(strconv.Itoa(n))...)
|
|
} else {
|
|
buf = append(buf, query[i])
|
|
}
|
|
}
|
|
return string(buf)
|
|
}
|