Skip to content

Commit

Permalink
fix: mysql管理密码随机化、密码存储、密码安全规则管理、字符串复杂度检测、生成随机密码、根据id查询账号规则
Browse files Browse the repository at this point in the history
  • Loading branch information
fanfanyangyang authored and iSecloud committed Sep 12, 2023
1 parent 3241d0f commit 161ce83
Show file tree
Hide file tree
Showing 30 changed files with 1,632 additions and 43 deletions.
37 changes: 19 additions & 18 deletions dbm-services/common/go-pubpkg/errno/50000_dbpriv_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,13 @@ package errno

var (
// dbpriv code start 50000

// PasswordNotConsistent TODO
PasswordNotConsistent = Errno{Code: 51008,
Message: "user is exist,but the new password is not consistent with the old password, should be consistent",
CNMessage: "账号已存在,但是新密码与旧密码不一致,需要保持一致"}
// GrantPrivilegesFail TODO
GrantPrivilegesFail = Errno{Code: 51009, Message: "Grant Privileges Fail", CNMessage: "授权执行失败"}
// GrantPrivilegesSuccess TODO
GrantPrivilegesSuccess = Errno{Code: 0, Message: "Grant Privileges success", CNMessage: "授权执行成功"}
// GrantPrivilegesParameterCheckFail TODO
GrantPrivilegesParameterCheckFail = Errno{Code: 51010, Message: "Parameter of Grant Privileges Check Fail",
CNMessage: "授权单据的参数检查失败"}
// ErrPswNotIdentical TODO
ErrPswNotIdentical = Errno{Code: 51000,
Message: "Password is not identical to the password of existed account rules, " +
"same accounts should use same password.",
CNMessage: "密码与已存在的账号规则中的密码不同,相同账号的密码需要保持一致!"}
// AccountRuleExisted TODO
AccountRuleExisted = Errno{Code: 51001, Message: "Account rule of user on this db is existed ",
CNMessage: "用户对此DB授权的账号规则已存在"}
Expand Down Expand Up @@ -57,10 +47,8 @@ var (
AccountRuleNotExisted = Errno{Code: 51004, Message: "Account rule not existed ", CNMessage: "账号规则不存在"}
// OnlyOneDatabaseAllowed TODO
OnlyOneDatabaseAllowed = Errno{Code: 51005,
Message: "Only one database allowed, database name should not contain space", CNMessage: "只允许填写一个数据库,数据库名称不能包含空格"}
// ErrMysqlInstanceStruct TODO
ErrMysqlInstanceStruct = Errno{Code: 51006, Message: "Not either tendbha or orphan structure",
CNMessage: "不符合tendbha或者orphan的集群结构"}
Message: "Only one database allowed, database name should not contain space",
CNMessage: "只允许填写一个数据库,数据库名称不能包含空格"}
// GenerateEncryptedPasswordErr TODO
GenerateEncryptedPasswordErr = Errno{Code: 51007, Message: "Generate Encrypted Password Err",
CNMessage: "创建账号,生成加密的密码时发生错误"}
Expand All @@ -70,11 +58,24 @@ var (
ClonePrivilegesCheckFail = Errno{Code: 51014, Message: "Clone privileges check fail", CNMessage: "克隆权限检查失败"}
// NoPrivilegesNothingToDo TODO
NoPrivilegesNothingToDo = Errno{Code: 51015, Message: "no privileges,nothing to do", CNMessage: "没有权限需要克隆"}
// IpPortFormatError TODO
IpPortFormatError = Errno{Code: 51017, Message: "format not in 'ip:port' format",
CNMessage: "格式不是ip:port的格式"}
// CloudIdRequired TODO
CloudIdRequired = Errno{Code: 51019, Message: "bk_cloud_id is required", CNMessage: "bk_cloud_id不能为空"}
// ClusterTypeIsEmpty TODO
ClusterTypeIsEmpty = Errno{Code: 51021, Message: "Cluster type can't be empty", CNMessage: "cluster type不能为空"}
ClusterTypeIsEmpty = Errno{Code: 51021, Message: "Cluster type can't be empty",
CNMessage: "cluster type不能为空"}
ModifyUserPasswordFail = Errno{Code: 51022, Message: "modify user password fail",
CNMessage: "修改用户密码失败"}
IncludeCharTypesLargerThanLength = Errno{Code: 51023, Message: "include char types larger than length",
CNMessage: "要求包含的字符类型大于字符串长度"}
TryTooManyTimes = Errno{Code: 51024, Message: "try too many times", CNMessage: "尝试太多次"}
RuleIdNull = Errno{Code: 51025, Message: "Rule ID should not be empty",
CNMessage: "安全规则的id不能为空"}
RuleNameNull = Errno{Code: 51026, Message: "Rule name should not be empty",
CNMessage: "安全规则的名称不能为空"}
RuleExisted = Errno{Code: 51027, Message: "Rule already existed ", CNMessage: "规则已存在"}
RuleNotExisted = Errno{Code: 51028, Message: "Rule not existed ", CNMessage: "规则不存在"}
NotMeetComplexity = Errno{Code: 51030, Message: "Set Passwords must meet complexity requirements",
CNMessage: "设置的密码应该符合密码复杂度"}
NameNull = Errno{Code: 51031, Message: "username should not be empty ",
CNMessage: "用户名名称不能为空"}
)
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ func CreatePartitionTicket(check Checker, objects []PartitionObject, zoneOffset
zone := fmt.Sprintf("%+03d:00", zoneOffset)
ticketType := "MYSQL_PARTITION"
if check.ClusterType == Tendbcluster {
ticketType = "SPIDER_PARTITION"
ticketType = "TENDBCLUSTER_PARTITION"
}
ticket := Ticket{BkBizId: check.BkBizId, TicketType: ticketType, Remark: "auto partition",
Details: Detail{Infos: []Info{{check.ConfigId, check.ClusterId, check.ImmuteDomain, *check.BkCloudId, objects}}}}
Expand Down
3 changes: 2 additions & 1 deletion dbm-services/mysql/db-priv/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ pubkey.pem
privkey.pem
infile
outfile
.code.yml
.code.yml
*.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS tb_security_rules;
DROP TABLE IF EXISTS tb_passwords;
30 changes: 30 additions & 0 deletions dbm-services/mysql/db-priv/assests/migrations/000004_init.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
SET NAMES utf8;
CREATE TABLE IF NOT EXISTS `tb_security_rules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL COMMENT '规则名称',
`rule` json NOT NULL COMMENT '安全规则',
`creator` varchar(800) NOT NULL COMMENT '创建者',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`operator` varchar(800) DEFAULT NULL COMMENT '最后一次变更者',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次变更时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `tb_passwords` (
`ip` varchar(100) NOT NULL COMMENT '实例ip',
`port` int unsigned NOT NULL COMMENT '实例端口',
`password` varchar(800) NOT NULL COMMENT '加密后的密码',
`username` varchar(800) NOT NULL COMMENT '用户名称',
`lock_until` timestamp COMMENT '锁定到的时间',
`operator` varchar(800) DEFAULT NULL COMMENT '最后一次变更者',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次变更时间',
UNIQUE KEY `idx_ip_port` (ip, port, username),
KEY `idx_lock` (`lock_until`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `tb_randomize_exclude` (
`username` varchar(800) NOT NULL COMMENT '用户名称',
`bk_biz_id` int(11) NOT NULL COMMENT '业务的 cmdb id',
`operator` varchar(800) DEFAULT NULL COMMENT '最后一次变更者',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次变更时间',
UNIQUE KEY `idx_username_bk_biz_id` (username, bk_biz_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

18 changes: 5 additions & 13 deletions dbm-services/mysql/db-priv/handler/account_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (m *PrivService) GetAccountRuleList(c *gin.Context) {
return
}

if err := json.Unmarshal(body, &input); err != nil {
if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
Expand All @@ -51,18 +51,14 @@ func (m *PrivService) AddAccountRule(c *gin.Context) {
return
}

if err := json.Unmarshal(body, &input); err != nil {
if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}

err = input.AddAccountRule(string(body))
if err != nil {
SendResponse(c, err, nil)
return
}
SendResponse(c, nil, nil)
SendResponse(c, err, nil)
return
}

Expand Down Expand Up @@ -102,17 +98,13 @@ func (m *PrivService) ModifyAccountRule(c *gin.Context) {
return
}

if err := json.Unmarshal(body, &input); err != nil {
if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}

err = input.ModifyAccountRule(string(body))
if err != nil {
SendResponse(c, err, nil)
return
}
SendResponse(c, nil, nil)
SendResponse(c, err, nil)
return
}
81 changes: 81 additions & 0 deletions dbm-services/mysql/db-priv/handler/admin_password.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package handler

import (
"dbm-services/common/go-pubpkg/errno"
"dbm-services/mysql/priv-service/service"
"encoding/json"
"io/ioutil"

"github.com/gin-gonic/gin"
"golang.org/x/exp/slog"
)

// GetPassword 查询用户的密码
func (m *PrivService) GetPassword(c *gin.Context) {
slog.Info("do GetPassword!")
var input service.GetPasswordPara
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
batch, err := input.GetPassword()
SendResponse(c, err, batch)
return

}

// ModifyPassword 新增或者修改密码
func (m *PrivService) ModifyPassword(c *gin.Context) {
slog.Info("do ModifyMysqlAdminPassword!")
var input service.ModifyPasswordPara
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
err = input.ModifyPassword()
SendResponse(c, err, nil)
return
}

// ModifyMysqlAdminPassword 新增或者修改mysql实例中管理用户的密码,可用于随机化密码
func (m *PrivService) ModifyMysqlAdminPassword(c *gin.Context) {
slog.Info("do ModifyMysqlAdminPassword!")
var input service.ModifyAdminUserPasswordPara

body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}

if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
// 随机化定时任务异步返回,避免占用资源
if input.Async == true {
SendResponse(c, nil, nil)
}
// 前端页面调用等同步返回,返回修改成功的实例以及没有修改成功的实例
batch, err := input.ModifyMysqlAdminPassword()
if input.Async == false {
SendResponse(c, err, batch)
}
return
}
45 changes: 45 additions & 0 deletions dbm-services/mysql/db-priv/handler/generate_random_string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package handler

import (
"dbm-services/common/go-pubpkg/errno"
"dbm-services/mysql/priv-service/service"
"encoding/base64"
"encoding/json"
"io/ioutil"

"github.com/gin-gonic/gin"
"golang.org/x/exp/slog"
)

// GenerateRandomString 生成随机化密码
func (m *PrivService) GenerateRandomString(c *gin.Context) {
slog.Info("do GenerateRandomString!")
var input service.GenerateRandomStringPara
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}

if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
if input.SecurityRuleName == "" {
SendResponse(c, errno.RuleNameNull, nil)
return
}
// 获取安全规则
security, err := service.GetSecurityRule(input.SecurityRuleName)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.RuleNameNull, nil)
return
}
password, err := service.GenerateRandomString(security)
// 传输base64,因为部分字符通过url传输会转义
SendResponse(c, err, base64.StdEncoding.EncodeToString([]byte(password)))
return
}
56 changes: 56 additions & 0 deletions dbm-services/mysql/db-priv/handler/randomize_manage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package handler

import (
"dbm-services/common/go-pubpkg/errno"
"dbm-services/mysql/priv-service/service"
"encoding/json"
"io/ioutil"

"github.com/gin-gonic/gin"
"golang.org/x/exp/slog"
)

// GetRandomExclude 获取不参加随机化的业务
func (m *PrivService) GetRandomExclude(c *gin.Context) {
slog.Info("do GetRandomExclude!")
var input service.RandomExcludePara
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}

if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
// 获取不参加随机化的业务
exclude, err := input.GetRandomizeExclude()
SendResponse(c, err, exclude)
return
}

// ModifyRandomExclude 修改不参与随机化的业务
func (m *PrivService) ModifyRandomExclude(c *gin.Context) {
slog.Info("do ModifyRandomExclude!")
var input service.RandomExcludePara

body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}

if err = json.Unmarshal(body, &input); err != nil {
slog.Error("msg", err)
SendResponse(c, errno.ErrBind, err)
return
}
// 传入的业务列表替换当前业务列表
err = input.ModifyRandomizeExclude(string(body))
SendResponse(c, err, nil)
return
}
20 changes: 20 additions & 0 deletions dbm-services/mysql/db-priv/handler/register_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ func (m *PrivService) Routes() []*gin.RouteInfo {

// 获取公钥,用于传输过程中加密密码
{Method: http.MethodPost, Path: "pub_key", HandlerFunc: m.GetPubKey},

// 修改实例中指定用户的密码
{Method: http.MethodPost, Path: "modify_mysql_admin_password", HandlerFunc: m.ModifyMysqlAdminPassword},
// 查询密码
{Method: http.MethodPost, Path: "get_password", HandlerFunc: m.GetPassword},
// 修改密码
{Method: http.MethodPost, Path: "modify_password", HandlerFunc: m.ModifyPassword},

// 生成随机字符串
{Method: http.MethodPost, Path: "get_random_string", HandlerFunc: m.GenerateRandomString},

// 安全规则
{Method: http.MethodPost, Path: "get_security_rule", HandlerFunc: m.GetSecurityRule},
{Method: http.MethodPost, Path: "add_security_rule", HandlerFunc: m.AddSecurityRule},
{Method: http.MethodPost, Path: "modify_security_rule", HandlerFunc: m.ModifySecurityRule},
{Method: http.MethodPost, Path: "delete_security_rule", HandlerFunc: m.DeleteSecurityRule},

// 不参与随机化的业务
{Method: http.MethodPost, Path: "get_randomize_exclude", HandlerFunc: m.GetRandomExclude},
{Method: http.MethodPost, Path: "modify_randomize_exclude", HandlerFunc: m.ModifyRandomExclude},
}
}

Expand Down
Loading

0 comments on commit 161ce83

Please sign in to comment.