mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix: 安全组同步优化,避免规则不同的安全组可以合并
This commit is contained in:
@@ -282,9 +282,16 @@ func (manager *SSecurityGroupRuleManager) getRulesBySecurityGroup(secgroup *SSec
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupRuleManager) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, secgroup *SSecurityGroup, rules []secrules.SecurityRule) compare.SyncResult {
|
||||
func (manager *SSecurityGroupRuleManager) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, secgroup *SSecurityGroup, rules secrules.SecurityRuleSet) compare.SyncResult {
|
||||
syncResult := compare.SyncResult{}
|
||||
priority, prePriority := 100, 0
|
||||
for i := 0; i < len(rules); i++ {
|
||||
// 这里避免了Rule规则优先级在 1-100之外的问题,ext.GetRules()不需要进行优先级转换
|
||||
if prePriority != 0 && rules[i].Priority != prePriority && priority > 1 {
|
||||
priority--
|
||||
}
|
||||
prePriority = rules[i].Priority
|
||||
rules[i].Priority = priority
|
||||
_, err := manager.newFromCloudSecurityGroup(ctx, userCred, rules[i], secgroup)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
|
||||
@@ -17,6 +17,7 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -79,18 +80,25 @@ func (manager *SSecurityGroupManager) ListItemFilter(ctx context.Context, q *sql
|
||||
return nil, httperrors.NewInputParameterError("Failed fetching secgroup %s", input.Equals)
|
||||
}
|
||||
secgroup := _secgroup.(*SSecurityGroup)
|
||||
inAllowList := secgroup.GetInAllowList()
|
||||
outAllowList := secgroup.GetOutAllowList()
|
||||
sq := manager.Query().NotEquals("id", secgroup.Id)
|
||||
secgroups := []SSecurityGroup{}
|
||||
err = db.FetchModelObjects(manager, sq, &secgroups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srs := secgroup.getSecurityGroupRuleSet()
|
||||
secgroupIds := []string{}
|
||||
for i := 0; i < len(secgroups); i++ {
|
||||
if srs.IsEqual(secgroups[i].getSecurityGroupRuleSet()) {
|
||||
secgroupIds = append(secgroupIds, secgroups[i].Id)
|
||||
_inAllowList := secgroups[i].GetInAllowList()
|
||||
if !inAllowList.Equals(_inAllowList) {
|
||||
continue
|
||||
}
|
||||
_outAllowList := secgroups[i].GetOutAllowList()
|
||||
if !outAllowList.Equals(_outAllowList) {
|
||||
continue
|
||||
}
|
||||
secgroupIds = append(secgroupIds, secgroups[i].Id)
|
||||
}
|
||||
q = q.In("id", secgroupIds)
|
||||
}
|
||||
@@ -490,16 +498,17 @@ func (self *SSecurityGroup) PerformClone(ctx context.Context, userCred mcclient.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) AllowPerformUnion(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "union")
|
||||
func (self *SSecurityGroup) AllowPerformMerge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "merge")
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) PerformUnion(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
secgroupIds := jsonutils.GetQueryStringArray(data, "secgroups")
|
||||
if len(secgroupIds) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("secgroups")
|
||||
}
|
||||
srs := self.getSecurityGroupRuleSet()
|
||||
inAllowList := self.GetInAllowList()
|
||||
outAllowList := self.GetOutAllowList()
|
||||
secgroups := []*SSecurityGroup{}
|
||||
for _, secgroupId := range secgroupIds {
|
||||
_secgroup, err := SecurityGroupManager.FetchByIdOrName(userCred, secgroupId)
|
||||
@@ -508,8 +517,12 @@ func (self *SSecurityGroup) PerformUnion(ctx context.Context, userCred mcclient.
|
||||
}
|
||||
secgroup := _secgroup.(*SSecurityGroup)
|
||||
secgroup.SetModelManager(SecurityGroupManager, secgroup)
|
||||
_srs := secgroup.getSecurityGroupRuleSet()
|
||||
if !srs.IsEqual(_srs) {
|
||||
_inAllowList := secgroup.GetInAllowList()
|
||||
if !inAllowList.Equals(_inAllowList) {
|
||||
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
|
||||
}
|
||||
_outAllowList := secgroup.GetOutAllowList()
|
||||
if !outAllowList.Equals(_outAllowList) {
|
||||
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
|
||||
}
|
||||
secgroups = append(secgroups, secgroup)
|
||||
@@ -530,6 +543,20 @@ func (self *SSecurityGroup) PerformUnion(ctx context.Context, userCred mcclient.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetOutAllowList() secrules.SecurityRuleSet {
|
||||
rules := self.GetSecRules("out")
|
||||
ruleSet := secrules.SecurityRuleSet(rules)
|
||||
rules = append(rules, *secrules.MustParseSecurityRule("out:allow any"))
|
||||
return ruleSet.AllowList()
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetInAllowList() secrules.SecurityRuleSet {
|
||||
rules := self.GetSecRules("in")
|
||||
rules = append(rules, *secrules.MustParseSecurityRule("in:deny any"))
|
||||
ruleSet := secrules.SecurityRuleSet(rules)
|
||||
return ruleSet.AllowList()
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) getSecurityGroupRuleSet() secrules.SecurityGroupRuleSet {
|
||||
rules := self.GetSecRules("")
|
||||
srs := secrules.SecurityGroupRuleSet{}
|
||||
@@ -607,14 +634,23 @@ func (manager *SSecurityGroupManager) getSecurityGroups() ([]SSecurityGroup, err
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) {
|
||||
srs := secrules.SecurityGroupRuleSet{}
|
||||
rules, err := extSec.GetRules()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inRules := secrules.SecurityRuleSet{}
|
||||
outRules := secrules.SecurityRuleSet{}
|
||||
for i := 0; i < len(rules); i++ {
|
||||
srs.AddRule(rules[i])
|
||||
if rules[i].Direction == secrules.DIR_IN {
|
||||
inRules = append(inRules, rules[i])
|
||||
} else {
|
||||
outRules = append(outRules, rules[i])
|
||||
}
|
||||
}
|
||||
sort.Sort(inRules)
|
||||
sort.Sort(outRules)
|
||||
inAllowList := inRules.AllowList()
|
||||
outAllowList := outRules.AllowList()
|
||||
|
||||
// 查询所有共享或与provider在同一项目的安全组,比对寻找一个与云上安全组规则相同的安全组
|
||||
secgroups := []SSecurityGroup{}
|
||||
@@ -632,8 +668,9 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
|
||||
log.Errorf("failed to fetch secgroups %v", err)
|
||||
}
|
||||
for _, secgroup := range secgroups {
|
||||
_srs := secgroup.getSecurityGroupRuleSet()
|
||||
if srs.IsEqual(_srs) {
|
||||
_inAllowList := secgroup.GetInAllowList()
|
||||
_outAllowList := secgroup.GetOutAllowList()
|
||||
if outAllowList.Equals(_outAllowList) && inAllowList.Equals(_inAllowList) {
|
||||
return &secgroup, nil
|
||||
}
|
||||
}
|
||||
@@ -657,7 +694,8 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
|
||||
}
|
||||
|
||||
//这里必须先同步下规则,不然下次对比此安全组规则为空
|
||||
SecurityGroupRuleManager.SyncRules(ctx, userCred, &secgroup, rules)
|
||||
SecurityGroupRuleManager.SyncRules(ctx, userCred, &secgroup, inRules)
|
||||
SecurityGroupRuleManager.SyncRules(ctx, userCred, &secgroup, outRules)
|
||||
|
||||
db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred)
|
||||
|
||||
|
||||
@@ -18,12 +18,14 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
@@ -1470,6 +1472,31 @@ func (self *SManagedVirtualizationRegionDriver) RequestSyncSecurityGroup(ctx con
|
||||
return "", errors.Wrap(err, "db.Update")
|
||||
}
|
||||
|
||||
inAllowList := secgroup.GetInAllowList()
|
||||
outAllowList := secgroup.GetOutAllowList()
|
||||
|
||||
rules, err := iSecgroup.GetRules()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iSecgroup.GetRules")
|
||||
}
|
||||
|
||||
inRules := secrules.SecurityRuleSet{}
|
||||
outRules := secrules.SecurityRuleSet{}
|
||||
for i := 0; i < len(rules); i++ {
|
||||
if rules[i].Direction == secrules.DIR_IN {
|
||||
inRules = append(inRules, rules[i])
|
||||
} else {
|
||||
outRules = append(outRules, rules[i])
|
||||
}
|
||||
}
|
||||
sort.Sort(inRules)
|
||||
sort.Sort(outRules)
|
||||
_inAllowList := inRules.AllowList()
|
||||
_outAllowList := outRules.AllowList()
|
||||
if inAllowList.Equals(_inAllowList) && outAllowList.Equals(_outAllowList) {
|
||||
return cache.ExternalId, nil
|
||||
}
|
||||
|
||||
err = iSecgroup.SyncRules(secgroup.GetSecRules(""))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iSecgroup.SyncRules")
|
||||
|
||||
Reference in New Issue
Block a user