From 5ce8acbf5f785449f9ef2c7cd8267e87134cdf1f Mon Sep 17 00:00:00 2001 From: Qu Xuan Date: Tue, 3 Dec 2019 18:27:58 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=89=E5=85=A8=E7=BB=84=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E4=BC=98=E5=8C=96,=E9=81=BF=E5=85=8D=E8=A7=84?= =?UTF-8?q?=E5=88=99=E4=B8=8D=E5=90=8C=E7=9A=84=E5=AE=89=E5=85=A8=E7=BB=84?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/models/secgrouprules.go | 9 ++- pkg/compute/models/secgroups.go | 66 ++++++++++++++++----- pkg/compute/regiondrivers/managedvirtual.go | 27 +++++++++ 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/pkg/compute/models/secgrouprules.go b/pkg/compute/models/secgrouprules.go index 3bd63df21e..854c6de4f5 100644 --- a/pkg/compute/models/secgrouprules.go +++ b/pkg/compute/models/secgrouprules.go @@ -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) diff --git a/pkg/compute/models/secgroups.go b/pkg/compute/models/secgroups.go index 6695131ecb..531f0f6d9f 100644 --- a/pkg/compute/models/secgroups.go +++ b/pkg/compute/models/secgroups.go @@ -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) diff --git a/pkg/compute/regiondrivers/managedvirtual.go b/pkg/compute/regiondrivers/managedvirtual.go index bae8b99f6e..cc1908730d 100644 --- a/pkg/compute/regiondrivers/managedvirtual.go +++ b/pkg/compute/regiondrivers/managedvirtual.go @@ -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")