Skip to content

Commit

Permalink
feat: 密码安全新版本_授权规则创建账号不允许用内部账号名_mysql支持replication_slave的特殊授权方式 Tence…
Browse files Browse the repository at this point in the history
  • Loading branch information
fanfanyangyang committed Sep 26, 2024
1 parent 6c13511 commit ef6bb68
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 214 deletions.
10 changes: 6 additions & 4 deletions dbm-services/common/go-pubpkg/errno/50000_dbpriv_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ var (
CNMessage: "检查没有通过"}
MigrateFail = Errno{Code: 51038, Message: "migrate fail",
CNMessage: "迁移失败"}
PortRequired = Errno{Code: 51039, Message: "port is required", CNMessage: "port不能为空"}
IpRequired = Errno{Code: 51040, Message: "ip is required", CNMessage: "ip列表不能为空"}
DomainRequired = Errno{Code: 51041, Message: "domain is required", CNMessage: "域名列表不能为空"}
QueryPrivilegesFail = Errno{Code: 51042, Message: "query privileges fail", CNMessage: "查询权限失败"}
PortRequired = Errno{Code: 51039, Message: "port is required", CNMessage: "port不能为空"}
IpRequired = Errno{Code: 51040, Message: "ip is required", CNMessage: "ip列表不能为空"}
DomainRequired = Errno{Code: 51041, Message: "domain is required", CNMessage: "域名列表不能为空"}
QueryPrivilegesFail = Errno{Code: 51042, Message: "query privileges fail", CNMessage: "查询权限失败"}
InternalAccountNameNotAllowed = Errno{Code: 51043, Message: "internal account name is not allowed",
CNMessage: "不允许使用内部账号名称"}
)
94 changes: 69 additions & 25 deletions dbm-services/mysql/db-priv/assests/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,42 +78,71 @@ func DoMigrateFromEmbed() error {
}

func DoMigratePlatformPassword() error {
// 初始化安全规则
// 通用的安全规则
passwordSecurityRule := &service.SecurityRulePara{Name: "password",
Rule: "{\"max_length\":12,\"min_length\":8,\"include_rule\":{\"numbers\":true,\"symbols\":true,\"lowercase\":true,\"uppercase\":true},\"exclude_continuous_rule\":{\"limit\":4,\"letters\":false,\"numbers\":false,\"symbols\":false,\"keyboards\":false,\"repeats\":false}}", Operator: "admin"}
b, _ := json.Marshal(passwordSecurityRule)
errOuter := passwordSecurityRule.AddSecurityRule(string(b), "add_security_rule")
if errOuter != nil {
no, _ := errno.DecodeErr(errOuter)
if no != errno.RuleExisted.Code {
return errOuter
// 兼容历史版本,避免未同步调整,引起旧规则无法使用
oldRules := []string{"password", "mongo_password", "redis_password", "simple_password"}
bigDataRule := "{\"max_length\":32,\"min_length\":6,\"include_rule\":{\"numbers\":true,\"symbols\":false,\"lowercase\":true,\"uppercase\":true},\"number_of_types\":2,\"symbols_allowed\":\"\",\"weak_password\":false,\"repeats\":4}"
mysqlSqlserverRule := "{\"max_length\":32,\"min_length\":6,\"include_rule\":{\"numbers\":true,\"symbols\":true,\"lowercase\":true,\"uppercase\":true},\"number_of_types\":2,\"symbols_allowed\":\"!#%&()*+,-./;<=>?[]^_{|}~@:$\",\"weak_password\":false,\"repeats\":4}"
redisRule := "{\"max_length\":32,\"min_length\":8,\"include_rule\":{\"numbers\":true,\"symbols\":true,\"lowercase\":true,\"uppercase\":true},\"number_of_types\":2,\"symbols_allowed\":\"#@%=+-;\",\"weak_password\":false,\"repeats\":4}"
mongodbRule := "{\"max_length\":32,\"min_length\":8,\"include_rule\":{\"numbers\":true,\"symbols\":true,\"lowercase\":true,\"uppercase\":true},\"number_of_types\":2,\"symbols_allowed\":\"#%=+-;\",\"weak_password\":false,\"repeats\":4}"
for _, old := range oldRules {
SecurityRulePara := &service.SecurityRulePara{Name: old}
rule, err := SecurityRulePara.GetSecurityRule()
if err != nil {
continue
}
var v2 string
switch old {
case "password":
v2 = mysqlSqlserverRule
case "mongo_password":
v2 = mongodbRule
case "redis_password":
v2 = redisRule
case "simple_password":
v2 = bigDataRule
default:
continue
}
SecurityRulePara = &service.SecurityRulePara{Id: rule.Id, Rule: v2, Operator: "deprecated"}
b, _ := json.Marshal(SecurityRulePara)
err = SecurityRulePara.ModifySecurityRule(string(b), "modify_security_rule")
if err != nil {
slog.Error("modify_security_rule", "name", old, "error", err)
}
}

// 不需要符号、固定长度的安全规则
NoSymbols := []string{"mongo_password", "redis_password", "simple_password"}
// mongodb专用的安全规则
for _, name := range NoSymbols {
passwordSecurityRule = &service.SecurityRulePara{Name: name,
Rule: "{\"max_length\":16,\"min_length\":16,\"include_rule\":{\"numbers\":true,\"symbols\":false,\"lowercase\":true,\"uppercase\":true},\"exclude_continuous_rule\":{\"limit\":4,\"letters\":false,\"numbers\":false,\"symbols\":false,\"keyboards\":false,\"repeats\":false}}", Operator: "admin"}
b, _ = json.Marshal(passwordSecurityRule)
errOuter = passwordSecurityRule.AddSecurityRule(string(b), "add_security_rule")
if errOuter != nil {
no, _ := errno.DecodeErr(errOuter)
if no != errno.RuleExisted.Code {
return errOuter
}
// 初始化新版本安全规则
// 密码服务V2版本,各个组件有独立的安全规则
bigData := []string{"es_password", "kafka_password", "hdfs_password", "pulsar_password", "influxdb_password"}
mysqlSqlserver := []string{"mysql_password", "tendbcluster_password", "sqlserver_password"}
for _, name := range bigData {
err := AddRule(name, bigDataRule)
if err != nil {
return err
}
}
for _, name := range mysqlSqlserver {
err := AddRule(name, mysqlSqlserverRule)
if err != nil {
return err
}
}
err := AddRule("redis_password_v2", redisRule)
if err != nil {
return err
}
err = AddRule("mongodb_password", mongodbRule)
if err != nil {
return err
}

// 初始化平台密码,随机密码
type ComponentPlatformUser struct {
Component string
Usernames []string
}

// 平台密码初始化,不存在新增
// 平台密码初始化,不存在则新增
var users []ComponentPlatformUser
users = append(users, ComponentPlatformUser{Component: "mysql", Usernames: []string{
"dba_bak_all_sel", "MONITOR", "MONITOR_ALL", "mysql", "repl", "yw", "partition_yw"}})
Expand All @@ -140,7 +169,7 @@ func DoMigratePlatformPassword() error {
Instances: []service.Address{{"0.0.0.0", &defaultInt, &defaultInt}},
InitPlatform: true, SecurityRuleName: "redis_password"}
}
b, _ = json.Marshal(*insertPara)
b, _ := json.Marshal(*insertPara)
err = insertPara.ModifyPassword(string(b), "modify_password")
if err != nil {
return fmt.Errorf("%s error: %s", "init platform password, modify password", err.Error())
Expand All @@ -151,6 +180,21 @@ func DoMigratePlatformPassword() error {
return nil
}

func AddRule(name string, content string) error {
rule := &service.SecurityRulePara{Name: name,
Rule: content, Operator: "admin"}
b, _ := json.Marshal(rule)
err := rule.AddSecurityRule(string(b), "add_security_rule")
if err != nil {
no, _ := errno.DecodeErr(err)
if no != errno.RuleExisted.Code {
slog.Error("add_rule", "name", name, "error", err)
return err
}
}
return nil
}

func ModifyPrivsGlobalToGlobalNon() error {
var rules []*service.TbAccountRules
err := service.DB.Self.Model(&service.TbAccountRules{}).Scan(&rules).Error
Expand Down
12 changes: 12 additions & 0 deletions dbm-services/mysql/db-priv/service/account.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package service

import (
"dbm-services/mysql/priv-service/util"
"encoding/hex"
"fmt"
"log/slog"
Expand Down Expand Up @@ -47,6 +48,17 @@ func (m *AccountPara) AddAccount(jsonPara string, ticket string) (TbAccounts, er
if count != 0 {
return detail, errno.AccountExisted.AddBefore(m.User)
}
innerAccount := make(map[string][]string)
innerAccount[sqlserver] = []string{"mssql_exporter", "dbm_admin", "sa", "sqlserver"}
innerAccount[mongodb] = []string{"dba", "apppdba", "monitor", "appmonitor"}
innerAccount[mysql] = []string{"gcs_admin", "gcs_dba", "monitor", "gm", "admin", "repl", "dba_bak_all_sel",
"yw", "partition_yw", "spider", "mysql.session", "mysql.sys", "gcs_spider", "sync"}
innerAccount[tendbcluster] = innerAccount[mysql]
if !m.MigrateFlag {
if util.HasElem(strings.ToLower(m.User), innerAccount[*m.ClusterType]) {
return detail, errno.InternalAccountNameNotAllowed
}
}
psw = m.Psw
// 从旧系统迁移的,不检查是否帐号和密码不同
if psw == m.User && !m.MigrateFlag {
Expand Down
27 changes: 26 additions & 1 deletion dbm-services/mysql/db-priv/service/add_priv.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"regexp"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -80,12 +81,27 @@ func (m *PrivTaskPara) AddPriv(jsonPara string, ticket string) error {
limit := rate.Every(time.Millisecond * 100) // QPS:10
burst := 10 // 桶容量 10
limiter := rate.NewLimiter(limit, burst)
for _, rule := range m.AccoutRules { // 添加权限,for acccountRuleList;for instanceList; do create a routine
for _, rule := range m.AccoutRules { // 添加权限,for accountRuleList;for instanceList; do create a routine
account, accountRule, outerErr := GetAccountRuleInfo(m.BkBizId, m.ClusterType, m.User, rule.Dbname)
if outerErr != nil {
AddErrorOnly(&errMsg, outerErr)
continue
}
repl := accountRule
var replFlag bool
// replication slave、replication client 权限在tendbha集群下,单独处理,授权方式与其他权限不同
for _, priv := range []string{"replication slave", "replication client"} {
if strings.Contains(accountRule.GlobalPriv, priv) {
replFlag = true
accountRule.GlobalPriv = strings.Replace(accountRule.GlobalPriv, priv, "", -1)
repl.GlobalPriv = fmt.Sprintf("%s,%s", repl.GlobalPriv, priv)
}
}
if replFlag {
repl.GlobalPriv = strings.Trim(repl.GlobalPriv, ",")
accountRule.GlobalPriv = strings.Trim(accountRule.GlobalPriv, ",")
accountRule.GlobalPriv = regexp.MustCompile(`,+`).ReplaceAllString(accountRule.GlobalPriv, ",")
}
for _, dns := range m.TargetInstances {
errLimiter := limiter.Wait(context.Background())
if errLimiter != nil {
Expand Down Expand Up @@ -140,6 +156,15 @@ func (m *PrivTaskPara) AddPriv(jsonPara string, ticket string) error {
if err != nil {
errMsgInner = append(errMsgInner, err.Error())
}
if replFlag {
// 在mysql实例上授权
err = ImportBackendPrivilege(account, repl, address, proxyIPs, m.SourceIPs,
instance.ClusterType, tendbhaMasterDomain, instance.BkCloudId, false,
true)
if err != nil {
errMsgInner = append(errMsgInner, err.Error())
}
}
}
if len(errMsgInner) > 0 {
AddErrorOnly(&errMsg, errors.New(failInfo+sep+strings.Join(errMsgInner, sep)))
Expand Down
11 changes: 7 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 @@ -214,10 +214,13 @@ func GenerateBackendSQL(account TbAccounts, rule TbAccountRules, ips []string, m
sql = fmt.Sprintf("%s '%s'@'%s' %s;", insertConnLogPriv, account.User, ip, identifiedByPassword)
sqlTemp = append(sqlTemp, sql)
}
if strings.Contains(strings.ToLower(rule.GlobalPriv), "show databases") {
sql = fmt.Sprintf(`GRANT SHOW DATABASES ON *.* TO '%s'@'%s' %s;`,
account.User, ip, identifiedByPassword)
sqlTemp = append(sqlTemp, sql)
slaveAllowedPriv := []string{"show databases", "replication slave", "replication client"}
for _, priv := range slaveAllowedPriv {
if strings.Contains(strings.ToLower(rule.GlobalPriv), priv) {
sql = fmt.Sprintf(`GRANT %s ON *.* TO '%s'@'%s' %s;`,
priv, account.User, ip, identifiedByPassword)
sqlTemp = append(sqlTemp, sql)
}
}
result.mu.Lock()
result.backendSQL = append(result.backendSQL, sqlTemp...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func CheckOrGetPassword(psw string, security SecurityRule) (string, error) {
password = psw
check := CheckPassword(security, []byte(psw))
if !check.IsStrength {
slog.Error("msg", "check", check)
return "", errno.NotMeetComplexity
}
} else {
Expand Down
Loading

0 comments on commit ef6bb68

Please sign in to comment.