Skip to content

Commit

Permalink
feat(mysql): mysql权限申请优化 TencentBlueKing#8650
Browse files Browse the repository at this point in the history
  • Loading branch information
xfwduke committed Dec 17, 2024
1 parent b8ef874 commit a52744c
Show file tree
Hide file tree
Showing 18 changed files with 478 additions and 598 deletions.
20 changes: 16 additions & 4 deletions dbm-services/mysql/db-priv/service/add_priv_base_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,14 @@ func GenerateBackendSQL(account TbAccounts, rule TbAccountRules, ips []string, m
}
// 备库域名只授予查询类权限
if clusterType == tendbha && tendbhaMasterDomain == false {
sql = fmt.Sprintf("GRANT SELECT, SHOW VIEW ON `%s`.* TO '%s'@'%s' %s;",
rule.Dbname, account.User, ip, identifiedByPassword)
if rule.Dbname == "%" || rule.Dbname == "*" {
sql = fmt.Sprintf("GRANT SELECT, SHOW VIEW ON *.* TO '%s'@'%s' %s;",
account.User, ip, identifiedByPassword)
} else {
sql = fmt.Sprintf("GRANT SELECT, SHOW VIEW ON `%s`.* TO '%s'@'%s' %s;",
rule.Dbname, account.User, ip, identifiedByPassword)
}

sqlTemp = append(sqlTemp, sql)
if containConnLogDBFlag {
sql = fmt.Sprintf("%s '%s'@'%s' %s;", insertConnLogPriv, account.User, ip, identifiedByPassword)
Expand All @@ -229,8 +235,14 @@ func GenerateBackendSQL(account TbAccounts, rule TbAccountRules, ips []string, m
}

if rule.DmlDdlPriv != "" {
sql = fmt.Sprintf("GRANT %s ON `%s`.* TO '%s'@'%s' %s;",
rule.DmlDdlPriv, rule.Dbname, account.User, ip, identifiedByPassword)
if rule.Dbname == "%" || rule.Dbname == "*" {
sql = fmt.Sprintf("GRANT %s ON *.* TO '%s'@'%s' %s;",
rule.DmlDdlPriv, account.User, ip, identifiedByPassword)
} else {
sql = fmt.Sprintf("GRANT %s ON `%s`.* TO '%s'@'%s' %s;",
rule.DmlDdlPriv, rule.Dbname, account.User, ip, identifiedByPassword)
}

sqlTemp = append(sqlTemp, sql)
if needInsertConnLogFlag {
sql = fmt.Sprintf("%s '%s'@'%s' %s;", insertConnLogPriv, account.User, ip, identifiedByPassword)
Expand Down
20 changes: 13 additions & 7 deletions dbm-services/mysql/db-priv/service/v2/add_priv/add_on_mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ func (c *PrivTaskPara) addOneDtOnMySQL(
dt *service.TbAccountRules,
reports map[string][]string,
) error {
var ipStr string
var oneBatchClients []string
for idx, ip := range clientIps {
// 限长 1500 代码会比较好些, 不往极限的 2000 搞
ipStr = ipStr + "," + ip
if len(ipStr) > 1500 || idx == len(clientIps)-1 {
slog.Info("add one dt on mysql", slog.String("ipstr", ipStr))
// 限长 100 代码会比较好些, 不往极限的 2000 搞
oneBatchClients = append(oneBatchClients, ip)
if len(oneBatchClients) > 100 || idx == len(clientIps)-1 {
slog.Info("add one dt on mysql", slog.Any("one batch client", oneBatchClients))
// 一次跑一批 client
err := c.addOneDtOnMySQLForSplitClient(
strings.Trim(ipStr, ","),
strings.Join(oneBatchClients, ","),
workingInstances,
accountAndRuleDetails,
psw,
Expand All @@ -82,7 +83,7 @@ func (c *PrivTaskPara) addOneDtOnMySQL(
slog.Error("add on mysql", slog.String("err", err.Error()))
return err
}
ipStr = ""
oneBatchClients = []string{}
}
}
return nil
Expand Down Expand Up @@ -152,6 +153,7 @@ func readOneDtRes(bkCloudId int64, res []*drs.OneAddressResult, reports map[stri
slog.String("addr", r.Address),
)
reports[r.Address] = []string{r.ErrorMsg}
continue
}
readOneAddrRes(bkCloudId, r, reports)
}
Expand All @@ -163,6 +165,10 @@ func readOneAddrRes(bkCloudId int64, r *drs.OneAddressResult, reports map[string
return
}

if _, ok := reports[r.Address]; !ok {
reports[r.Address] = make([]string, 0)
}

_, sqlStat, msgText, isException := internal.ParseMySQLErrStr(errMsg)
if !isException {
reports[r.Address] = append(reports[r.Address], msgText)
Expand Down
15 changes: 12 additions & 3 deletions dbm-services/mysql/db-priv/service/v2/add_priv/add_priv.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"dbm-services/mysql/priv-service/service/v2/internal"
"encoding/json"
"log/slog"
"strings"
"time"

"github.com/pkg/errors"
Expand All @@ -17,7 +18,9 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
slog.String("jsonPara", jsonPara),
)

if c.ClusterType == internal.ClusterTypeSqlServerHA || c.ClusterType == internal.ClusterTypeSqlServer || c.ClusterType == internal.ClusterTypeSqlServerSingle {
if c.ClusterType == internal.ClusterTypeSqlServerHA ||
c.ClusterType == internal.ClusterTypeSqlServer ||
c.ClusterType == internal.ClusterTypeSqlServerSingle {
return c.AddPrivForSqlserver(jsonPara)
}

Expand All @@ -39,6 +42,8 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
// targetInstance 传入的其实全是域名
c.TargetInstances = internal.UniqueStringSlice(c.TargetInstances)

slog.Info("add priv", slog.String("source ips", strings.Join(c.SourceIPs, ",")))

// 写审计日志
service.AddPrivLog(
service.PrivLog{
Expand All @@ -56,6 +61,7 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
slog.Error("add priv", slog.String("err", err.Error()))
return err
}
slog.Info("add priv", slog.Any("target meta infos", targetMetaInfos))

/*
TenDBSingle 授权是在存储实例操作
Expand All @@ -64,6 +70,7 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
*/

// 开白名单
// proxy 白名单是前置集中开, 所有出错了直接返回
if c.ClusterType == internal.ClusterTypeTenDBHA {
err = c.addWhiteList(targetMetaInfos)
if err != nil {
Expand All @@ -80,7 +87,7 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
clientIps, workingMySQLInstances := c.prepareMySQLPayload(targetMetaInfos)
slog.Info(
"add priv",
slog.Any("clientIps", clientIps),
slog.String("clientIps", strings.Join(clientIps, ",")),
slog.Any("workingMySQLInstances", workingMySQLInstances),
)

Expand All @@ -96,6 +103,8 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
slog.String("accountAndRuleDetails", accountAndRuleDetails.String()),
)

// err 是调用函数出错, 直接报错返回
// reports 是实施授权的报告
reports, err := c.addOnMySQL(clientIps, workingMySQLInstances, accountAndRuleDetails)
if err != nil {
slog.Error("add priv", slog.String("err", err.Error()))
Expand All @@ -111,6 +120,6 @@ func (c *PrivTaskPara) AddPriv(jsonPara, ticket string) (err error) {
return errors.New(string(b))
}

slog.Info("add priv finish", slog.Any("reports", reports))
slog.Info("add priv finish")
return nil
}
110 changes: 54 additions & 56 deletions dbm-services/mysql/db-priv/service/v2/add_priv/add_proxy_white_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,71 +33,54 @@ func (c *PrivTaskPara) addWhiteList(targetMetaInfos []*service.Instance) (err er
slog.Any("proxies", workingProxies),
)

// 确实有要操作的 proxy
if len(workingProxies) > 0 {
var cmds []string
for _, clientIp := range c.SourceIPs {
//clientIp 可能是 localhost, 要忽略
if clientIp == "localhost" {
continue
}
cmds = append(
cmds,
fmt.Sprintf(`refresh_users('%s@%s', '+')`,
c.User, clientIp,
))
}
if len(workingProxies) <= 0 {
return nil
}

cmds := generateProxyCmds(c.SourceIPs, c.User)
slog.Info(
"add proxy white list",
slog.Any("cmds", cmds),
)

// drs 执行多个 sql 是循环一个一个来的
// 所以批量发送是可以的, 只是这么搞 drs 负载估计要炸
// 这里搞并发的意义不大
var errCollect error
for bkCloudId, addresses := range workingProxies {
slog.Info(
"add proxy white list",
slog.Any("cmds", cmds),
slog.Int64("bk_cloud_id", bkCloudId),
slog.Any("addresses", addresses),
)
drsRes, err := drs.RPCProxyAdmin(
bkCloudId,
addresses,
cmds,
false,
0,
)
if err != nil {
slog.Error("add proxy white list", slog.String("err", err.Error()))
return err
}

// drs 执行多个 sql 是循环一个一个来的
// 所以批量发送是可以的, 只是这么搞 drs 负载估计要炸
// 这里搞并发的意义不大
var errCollect error
for bkCloudId, addresses := range workingProxies {
// 错误要收集起来
ec := collectErrors(drsRes)
if ec != nil {
slog.Error("add proxy white list", slog.String("err collection", ec.Error()))
errCollect = errors.Join(errCollect, ec)
} else {
slog.Info(
"add proxy white list",
"add proxy white list success",
slog.Int64("bk_cloud_id", bkCloudId),
slog.Any("addresses", addresses),
)
drsRes, err := drs.RPCProxyAdmin(
bkCloudId,
addresses,
cmds,
false,
0,
)
if err != nil {
slog.Error(
"add proxy white list",
slog.Int64("bk_cloud_id", bkCloudId),
slog.String("err", err.Error()),
)
return err
}

// 错误要收集起来
ec := collectErrors(drsRes)
if ec != nil {
slog.Error(
"add proxy white list",
slog.Int64("bk_cloud_id", bkCloudId),
slog.String("err", ec.Error()),
)
errCollect = errors.Join(errCollect, ec)
} else {
slog.Info(
"add proxy white list success",
slog.Int64("bk_cloud_id", bkCloudId),
)
}
}
if errCollect != nil {
return errCollect
}
}
if errCollect != nil {
return errCollect
}

return nil
}

Expand All @@ -120,3 +103,18 @@ func collectErrors(res []*drs.OneAddressResult) (ec error) {
}
return ec
}

func generateProxyCmds(clientIps []string, username string) (cmds []string) {
for _, clientIp := range clientIps {
//clientIp 可能是 localhost, 要忽略
if clientIp == "localhost" {
continue
}
cmds = append(
cmds,
fmt.Sprintf(`refresh_users('%s@%s', '+')`,
username, clientIp,
))
}
return cmds
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (c *PrivTaskPara) fetchTargetDBMetaInfo() ([]*service.Instance, error) {
)
return nil, err
}
slog.Info("fetch target db meta info", slog.Any("result", result))

res := make([]*service.Instance, 0)
err = json.Unmarshal(result.Data, &res)
Expand Down
13 changes: 11 additions & 2 deletions dbm-services/mysql/db-priv/service/v2/add_priv/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"dbm-services/mysql/priv-service/service/v2/internal"
"fmt"
"log/slog"
"strings"
)

func (c *PrivTaskPara) prepareMySQLPayload(targetMetaInfos []*service.Instance) (
Expand All @@ -27,7 +28,7 @@ func (c *PrivTaskPara) prepareMySQLPayload(targetMetaInfos []*service.Instance)
func (c *PrivTaskPara) prepareTenDBSingle(targetMetaInfos []*service.Instance) (
clientIps []string,
workingMySQLInstances map[int64][]string) {
clientIps = make([]string, 0)
clientIps = c.SourceIPs
workingMySQLInstances = make(map[int64][]string)

for _, ele := range targetMetaInfos {
Expand Down Expand Up @@ -58,13 +59,21 @@ func (c *PrivTaskPara) prepareTenDBHA(targetMetaInfos []*service.Instance) (

// 申请主域名权限要把来源替换为 proxy ip
// 如果集群有 padding proxy 属性, 则是把 proxy ip 追加到 client ip 里
slog.Info(
"prepare tendbha",
slog.String("bind to", ele.BindTo),
slog.Bool("padding proxy", ele.PaddingProxy),
)
if ele.BindTo == internal.MachineTypeProxy {
if ele.PaddingProxy {
clientIps = append(clientIps, proxyIps...)
} else {
clientIps = proxyIps
}
} else {
clientIps = c.SourceIPs
}
slog.Info("prepare tendbha", slog.String("clientIps", strings.Join(clientIps, ",")))
// TenDBHA 要在所有存储实例执行授权
for _, s := range ele.Storages {
if _, ok := workingMySQLInstances[ele.BkCloudId]; !ok {
Expand All @@ -81,7 +90,7 @@ func (c *PrivTaskPara) prepareTenDBHA(targetMetaInfos []*service.Instance) (
}

func (c *PrivTaskPara) prepareTenDBCluster(targetMetaInfos []*service.Instance) (clientIps []string, workingMySQLInstances map[int64][]string) {
clientIps = make([]string, 0)
clientIps = c.SourceIPs
workingMySQLInstances = make(map[int64][]string)

// 对应的 spider 上执行授权
Expand Down
Loading

0 comments on commit a52744c

Please sign in to comment.