支持批量添加安全组规则

This commit is contained in:
屈轩
2019-01-04 11:41:36 +08:00
parent 1a44405e1b
commit 0ac4a7bff4
4 changed files with 108 additions and 110 deletions

View File

@@ -99,6 +99,7 @@ func init() {
Name string `help:"Name of security group to update"`
Desc string `help:"Description of security groups"`
}
R(&SecGroupsUpdateOptions{}, "secgroup-update", "Update details of a security group", func(s *mcclient.ClientSession, args *SecGroupsUpdateOptions) error {
params := jsonutils.NewDict()
if len(args.Name) > 0 {
@@ -114,53 +115,25 @@ func init() {
printObject(secgroups)
return nil
})
type SecGroupsUpdateRulesOptions struct {
ID string `help:"ID or Name of security group"`
RULES []string `help:"security rule to create"`
type SecGroupsAddRuleOptions struct {
ID string `help:"ID or Name of security group"`
DIRECTION string `help:"Direction of rule" choices:"in|out"`
PROTOCOL string `help:"Protocol of rule" choices:"any|tcp|udp|icmp"`
ACTION string `help:"Actin of rule" choices:"allow|deny"`
PRIORITY int `help:"Priority for rule, range 1 ~ 100"`
Cidr string `help:"IP or CIRD for rule"`
Description string `help:"Desciption for rule"`
Ports string `help:"Port for rule"`
}
R(&SecGroupsUpdateRulesOptions{}, "secgroup-add-rules", "Add security rules to a security group", func(s *mcclient.ClientSession, args *SecGroupsUpdateRulesOptions) error {
params := jsonutils.NewDict()
if len(args.RULES) > 0 {
for i, a := range args.RULES {
params.Add(jsonutils.NewString(a), fmt.Sprintf("rule.%d", i))
}
}
result, err := modules.SecGroups.PerformAction(s, args.ID, "add-rules", params)
R(&SecGroupsAddRuleOptions{}, "secgroup-add-rule", "Add rule for a security group", func(s *mcclient.ClientSession, args *SecGroupsAddRuleOptions) error {
params, err := options.StructToParams(args)
secgroups, err := modules.SecGroups.PerformAction(s, args.ID, "add-rule", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&SecGroupsUpdateRulesOptions{}, "secgroup-remove-rules", "Remove security rules from a security group", func(s *mcclient.ClientSession, args *SecGroupsUpdateRulesOptions) error {
params := jsonutils.NewDict()
if len(args.RULES) > 0 {
for i, a := range args.RULES {
params.Add(jsonutils.NewString(a), fmt.Sprintf("rule.%d", i))
}
}
result, err := modules.SecGroups.PerformAction(s, args.ID, "remove-rules", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&SecGroupsUpdateRulesOptions{}, "secgroup-set-rules", "Set security rules from a security group", func(s *mcclient.ClientSession, args *SecGroupsUpdateRulesOptions) error {
params := jsonutils.NewDict()
if len(args.RULES) > 0 {
for i, a := range args.RULES {
params.Add(jsonutils.NewString(a), fmt.Sprintf("rule.%d", i))
}
}
result, err := modules.SecGroups.PerformAction(s, args.ID, "set-rules", params)
if err != nil {
return err
}
printObject(result)
printObject(secgroups)
return nil
})
}

View File

@@ -166,40 +166,10 @@ func (manager *SSecurityGroupRuleManager) ValidateCreateData(ctx context.Context
PortEnd: -1,
}
ports, _ := data.GetString("ports")
var err error
if len(ports) > 0 {
if strings.Index(ports, "-") > 0 {
portsInfo := strings.Split(ports, "-")
if len(portsInfo) != 2 {
return nil, httperrors.NewInputParameterError("invalid ports: %s", ports)
}
rule.PortStart, err = strconv.Atoi(portsInfo[0])
if err != nil {
return nil, httperrors.NewInputParameterError("invalid port start: %s", portsInfo[0])
}
rule.PortEnd, err = strconv.Atoi(portsInfo[1])
if err != nil {
return nil, httperrors.NewInputParameterError("invalid port end: %s", portsInfo[1])
}
} else if strings.Index(ports, ",") > 0 {
for _, port := range strings.Split(ports, ",") {
_port, err := strconv.Atoi(port)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid port : %d", port)
}
rule.Ports = append(rule.Ports, _port)
}
} else {
port, err := strconv.Atoi(ports)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid ports: %s", ports)
}
rule.Ports = append(rule.Ports, port)
}
if err := rule.ParsePorts(ports); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
err = rule.ValidateRule()
if err != nil {
if err := rule.ValidateRule(); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
return manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)

View File

@@ -9,6 +9,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -166,6 +167,49 @@ func totalSecurityGroupCount(projectId string) int {
return q.Count()
}
func (self *SSecurityGroup) AllowPerformAddRule(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "add-rule")
}
func (self *SSecurityGroup) PerformAddRule(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
secgrouprule := &SSecurityGroupRule{SecgroupID: self.Id}
secgrouprule.SetModelManager(SecurityGroupRuleManager)
secgrouprule.Direction, _ = data.GetString("direction")
secgrouprule.Action, _ = data.GetString("action")
secgrouprule.Priority, _ = data.Int("priority")
secgrouprule.Description, _ = data.GetString("description")
secgrouprule.Protocol, _ = data.GetString("protocol")
secgrouprule.CIDR, _ = data.GetString("cidr")
if len(secgrouprule.CIDR) > 0 {
if !regutils.MatchCIDR(secgrouprule.CIDR) && !regutils.MatchIPAddr(secgrouprule.CIDR) {
return nil, httperrors.NewInputParameterError("invalid ip address: %s", secgrouprule.CIDR)
}
} else {
secgrouprule.CIDR = "0.0.0.0/0"
}
rule := secrules.SecurityRule{
Priority: int(secgrouprule.Priority),
Direction: secrules.TSecurityRuleDirection(secgrouprule.Direction),
Action: secrules.TSecurityRuleAction(secgrouprule.Action),
Protocol: secgrouprule.Protocol,
Ports: []int{},
PortStart: -1,
PortEnd: -1,
}
ports, _ := data.GetString("ports")
if err := rule.ParsePorts(ports); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
if err := rule.ValidateRule(); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
if err := SecurityGroupRuleManager.TableSpec().Insert(secgrouprule); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
self.DoSync(ctx, userCred)
return nil, nil
}
func (self *SSecurityGroup) AllowPerformClone(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return true
}

View File

@@ -149,42 +149,11 @@ func ParseSecurityRule(pattern string) (*SecurityRule, error) {
}
rule.Protocol = seg
} else if status == SEG_PORT {
if len(seg) == 0 {
status = SEG_END
} else if idx := strings.Index(seg, "-"); idx > -1 {
segs := strings.SplitN(seg, "-", 2)
var ps, pe int
var err error
if ps, err = parsePortString(segs[0]); err != nil {
return nil, ErrInvalidPortRange
}
if pe, err = parsePortString(segs[1]); err != nil {
return nil, ErrInvalidPortRange
}
if ps > pe {
ps, pe = pe, ps
}
rule.PortStart = ps
rule.PortEnd = pe
} else if idx := strings.Index(seg, ","); idx > -1 {
ports := make([]int, 0)
segs := strings.Split(seg, ",")
for _, seg := range segs {
p, err := parsePortString(seg)
if err != nil {
return nil, err
}
ports = append(ports, p)
}
rule.Ports = ports
} else {
p, err := parsePortString(seg)
if err != nil {
return nil, err
}
rule.PortStart, rule.PortEnd = p, p
}
status = SEG_END
if err := rule.ParsePorts(seg); err != nil {
return nil, err
}
return rule, nil
}
}
return rule, nil
@@ -198,6 +167,48 @@ func (rule *SecurityRule) IsWildMatch() bool {
rule.PortEnd == 0
}
func (rule *SecurityRule) ParsePorts(seg string) error {
if len(seg) == 0 {
rule.Ports = []int{}
rule.PortStart = -1
rule.PortEnd = -1
return nil
} else if idx := strings.Index(seg, "-"); idx > -1 {
segs := strings.SplitN(seg, "-", 2)
var ps, pe int
var err error
if ps, err = parsePortString(segs[0]); err != nil {
return ErrInvalidPortRange
}
if pe, err = parsePortString(segs[1]); err != nil {
return ErrInvalidPortRange
}
if ps > pe {
ps, pe = pe, ps
}
rule.PortStart = ps
rule.PortEnd = pe
} else if idx := strings.Index(seg, ","); idx > -1 {
ports := make([]int, 0)
segs := strings.Split(seg, ",")
for _, seg := range segs {
p, err := parsePortString(seg)
if err != nil {
return err
}
ports = append(ports, p)
}
rule.Ports = ports
} else {
p, err := parsePortString(seg)
if err != nil {
return err
}
rule.PortStart, rule.PortEnd = p, p
}
return nil
}
func (rule *SecurityRule) ValidateRule() error {
if !utils.IsInStringArray(string(rule.Direction), []string{string(DIR_IN), string(DIR_OUT)}) {
return ErrInvalidDirection