add: 支持创建安全组时同时创建规则

This commit is contained in:
ioito
2019-09-26 18:04:09 +08:00
parent 49a2c10dec
commit c245e147ad
4 changed files with 185 additions and 38 deletions
+53 -1
View File
@@ -9,6 +9,58 @@ SecgroupCreate:
type: string
example: secgrou-description
description: 安全组描述
rules:
type: array
items:
$ref: '#/SecgroupRuleCreate'
SecgroupRuleCreate:
type: object
properties:
priority:
type: integer
example: 34
default: 1
description: 安全组优先级,数字越高,优先级越高 范围 1-100
protocol:
type: string
example: icmp
enum: [icmp, tcp, udp, any]
requried: true
description: 协议
ports:
type: string
example: 10-200
description: 端口或端口范围
direction:
type: string
example: in
enum: [in, out]
requried: true
description: 规则出入方向
cidr:
type: string
example: 0.0.0.0/0
default: "0.0.0.0/0"
description: IP地址或网络地址
action:
type: string
example: allow
enum: [allow, deny]
requried: true
description: 允许或拒绝
port_start:
type: integer
example: 10
description: 和port_end参数配合使用,若指定ports则此参数失效
port_end:
type: integer
example: 100
description: 和port_start参数配合使用,若指定ports则此参数失效
description:
type: string
example: test-description
description: 规则描述信息
SecgroupResponse:
type: object
@@ -103,4 +155,4 @@ SecgroupAddRule:
description:
type: string
example: test-rule
description: 规则描述
description: 规则描述
+70
View File
@@ -0,0 +1,70 @@
package compute
import (
"fmt"
"github.com/pkg/errors"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
)
type SSecgroupRuleCreateInput struct {
apis.Meta
Priority int
Protocol string
Ports string
PortStart int
PortEnd int
Direction string
CIDR string
Action string
Description string
SecgroupId string
}
func (input *SSecgroupRuleCreateInput) Check() error {
rule := secrules.SecurityRule{
Priority: input.Priority,
Direction: secrules.TSecurityRuleDirection(input.Direction),
Action: secrules.TSecurityRuleAction(input.Action),
Protocol: input.Protocol,
PortStart: input.PortStart,
PortEnd: input.PortEnd,
Ports: []int{},
}
if len(input.Ports) > 0 {
err := rule.ParsePorts(input.Ports)
if err != nil {
return errors.Wrapf(err, "ParsePorts(%s)", input.Ports)
}
}
if len(input.CIDR) > 0 {
if !regutils.MatchCIDR(input.CIDR) && !regutils.MatchIPAddr(input.CIDR) {
return fmt.Errorf("invalid ip address: %s", input.CIDR)
}
} else {
input.CIDR = "0.0.0.0/0"
}
if rule.PortStart > 0 && rule.PortEnd > 0 {
if rule.PortStart != rule.PortEnd {
input.Ports = fmt.Sprintf("%d-%d", rule.PortStart, rule.PortEnd)
} else {
input.Ports = fmt.Sprintf("%d", input.PortStart)
}
}
return rule.ValidateRule()
}
type SSecgroupCreateInput struct {
apis.Meta
Name string
Description string
Rules []SSecgroupRuleCreateInput
}
+19 -36
View File
@@ -23,13 +23,14 @@ 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/util/stringutils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
@@ -148,47 +149,29 @@ func (self *SSecurityGroupRule) BeforeInsert() {
}
func (manager *SSecurityGroupRuleManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
defsecgroup, _ := data.GetString("secgroup")
if len(defsecgroup) == 0 {
return nil, httperrors.NewMissingParameterError("secgroup")
}
secgroup, _ := SecurityGroupManager.FetchByIdOrName(userCred, defsecgroup)
if secgroup == nil {
return nil, httperrors.NewInputParameterError("Security Group %s not found", defsecgroup)
}
data.Add(jsonutils.NewString(secgroup.GetId()), "secgroup_id")
priority, _ := data.Int("priority")
direction, _ := data.GetString("direction")
action, _ := data.GetString("action")
cidr, _ := data.GetString("cidr")
protocol, _ := data.GetString("protocol")
if len(cidr) > 0 {
if !regutils.MatchCIDR(cidr) && !regutils.MatchIPAddr(cidr) {
return nil, httperrors.NewInputParameterError("invalid ip address: %s", cidr)
}
} else {
data.Add(jsonutils.NewString("0.0.0.0/0"), "cidr")
secgroupV := validators.NewModelIdOrNameValidator("secgroup", "secgroup", ownerId)
err := secgroupV.Validate(data)
if err != nil {
return nil, err
}
rule := secrules.SecurityRule{
Priority: int(priority),
Direction: secrules.TSecurityRuleDirection(direction),
Action: secrules.TSecurityRuleAction(action),
Protocol: protocol,
Ports: []int{},
PortStart: -1,
PortEnd: -1,
input := &api.SSecgroupRuleCreateInput{}
err = data.Unmarshal(input)
if err != nil {
return nil, httperrors.NewInputParameterError("Failed to unmarshal input: %v", err)
}
ports, _ := data.GetString("ports")
if err := rule.ParsePorts(ports); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
err = input.Check()
if err != nil {
return nil, err
}
if err := rule.ValidateRule(); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
data, err = manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
if err != nil {
return nil, err
}
return manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
return input.JSON(input), nil
}
func (self *SSecurityGroupRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+43 -1
View File
@@ -231,7 +231,49 @@ func (manager *SSecurityGroupManager) ValidateCreateData(
data *jsonutils.JSONDict,
) (*jsonutils.JSONDict, error) {
// TODO: check set pending quota
return manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := &api.SSecgroupCreateInput{}
err := data.Unmarshal(input)
if err != nil {
return nil, httperrors.NewInputParameterError("Failed to unmarshal input: %v", err)
}
for i, rule := range input.Rules {
err = rule.Check()
if err != nil {
return nil, httperrors.NewInputParameterError("rule %d is invalid: %s", i, err)
}
}
data, err = manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
if err != nil {
return nil, err
}
return input.JSON(input), nil
}
func (self *SSecurityGroup) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SSharableVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
input := &api.SSecgroupCreateInput{}
data.Unmarshal(input)
for _, r := range input.Rules {
rule := &SSecurityGroupRule{
Priority: int64(r.Priority),
Protocol: r.Protocol,
Ports: r.Ports,
Direction: r.Direction,
CIDR: r.CIDR,
Action: r.Action,
Description: r.Description,
SecgroupID: self.Id,
}
SecurityGroupRuleManager.TableSpec().Insert(rule)
}
}
func (manager *SSecurityGroupManager) FetchSecgroupById(secId string) *SSecurityGroup {