fix(region): optimized peer secgroup

This commit is contained in:
Qu Xuan
2021-04-20 15:23:41 +08:00
parent 8154628011
commit c28f3f68aa
9 changed files with 390 additions and 156 deletions
+234 -98
View File
@@ -57,6 +57,9 @@ const DEFAULT_SRC_RULE_ID = "default_src_rule_id"
type SecRuleInfo struct {
InDefaultRule SecurityRule
OutDefaultRule SecurityRule
in SecurityRuleSet
out SecurityRuleSet
rules SecurityRuleSet
Rules SecurityRuleSet
MinPriority int
MaxPriority int
@@ -64,10 +67,26 @@ type SecRuleInfo struct {
IsSupportPeerSecgroup bool
}
func (r SecRuleInfo) getOffest(priority int) (int, int) {
if r.MinPriority < r.MaxPriority {
if priority >= r.MaxPriority {
return priority, -1
}
return priority + 1, 0
} else {
if priority <= r.MaxPriority {
return priority, 1
}
return priority - 1, 0
}
}
func (r SecRuleInfo) AddDefaultRule(d SecRuleInfo, inRules, outRules []SecurityRule, isSrc bool) ([]SecurityRule, []SecurityRule) {
min, max := r.MinPriority, r.MaxPriority
r.InDefaultRule.Priority = min + 1
r.OutDefaultRule.Priority = min + 1
r.InDefaultRule.minPriority, r.InDefaultRule.maxPriority = r.MinPriority, r.MaxPriority
r.OutDefaultRule.minPriority, r.OutDefaultRule.maxPriority = r.MinPriority, r.MaxPriority
if max >= min {
r.InDefaultRule.Priority = min - 1
r.OutDefaultRule.Priority = min - 1
@@ -81,8 +100,21 @@ func (r SecRuleInfo) AddDefaultRule(d SecRuleInfo, inRules, outRules []SecurityR
r.OutDefaultRule.ExternalId = DEFAULT_DEST_RULE_ID
}
inRules = append(inRules, r.InDefaultRule)
outRules = append(outRules, r.OutDefaultRule)
var isWideRule = func(rules []SecurityRule) bool {
for _, rule := range rules {
if strings.HasSuffix(rule.String(), "allow any") || strings.HasSuffix(rule.String(), "deny any") {
return true
}
}
return false
}
if !isWideRule(inRules) {
inRules = append(inRules, r.InDefaultRule)
}
if !isWideRule(outRules) {
outRules = append(outRules, r.OutDefaultRule)
}
return inRules, outRules
}
@@ -101,6 +133,10 @@ type SecurityGroupCreateInput struct {
}
type SecurityRule struct {
minPriority int
maxPriority int
offset int
secrules.SecurityRule
Name string
ExternalId string
@@ -109,6 +145,11 @@ type SecurityRule struct {
PeerSecgroupId string
}
func (self *SecurityRule) addPriority(offset int) {
self.Priority += offset
self.offset += offset
}
func (r SecurityRule) String() string {
if len(r.PeerSecgroupId) == 0 {
return r.SecurityRule.String()
@@ -118,19 +159,25 @@ func (r SecurityRule) String() string {
type SecurityRuleSet []SecurityRule
func (rules SecurityRuleSet) Split(isSupportPeerSecgroup bool) (in, out SecurityRuleSet, isStandardRules bool) {
isStandardRules = true
for i := 0; i < len(rules); i++ {
if len(rules[i].PeerSecgroupId) > 0 {
isStandardRules = false
func (self *SecRuleInfo) Split() (in, out SecurityRuleSet) {
self.rules = SecurityRuleSet{}
self.in = SecurityRuleSet{}
self.out = SecurityRuleSet{}
for i := 0; i < len(self.Rules); i++ {
self.rules = append(self.rules, self.Rules[i])
if self.Rules[i].Direction == secrules.DIR_IN {
self.in = append(self.in, self.Rules[i])
} else {
self.out = append(self.out, self.Rules[i])
}
if !isSupportPeerSecgroup && len(rules[i].PeerSecgroupId) > 0 {
self.Rules[i].minPriority, self.Rules[i].maxPriority = self.MinPriority, self.MaxPriority
if !self.IsSupportPeerSecgroup && len(self.Rules[i].PeerSecgroupId) > 0 {
continue
}
if rules[i].Direction == secrules.DIR_IN {
in = append(in, rules[i])
if self.Rules[i].Direction == secrules.DIR_IN {
in = append(in, self.Rules[i])
} else {
out = append(out, rules[i])
out = append(out, self.Rules[i])
}
}
return
@@ -145,29 +192,63 @@ func (srs SecurityRuleSet) Swap(i, j int) {
}
func (srs SecurityRuleSet) Less(i, j int) bool {
return srs[i].Priority < srs[j].Priority || (srs[i].Priority == srs[j].Priority && srs[i].String() < srs[j].String())
if srs[i].Priority < srs[j].Priority {
return true
}
if srs[i].Priority > srs[j].Priority {
return false
}
if len(srs) > 0 {
if (srs[0].minPriority <= srs[0].maxPriority && srs[i].String() < srs[j].String()) ||
(srs[0].minPriority > srs[0].maxPriority && srs[i].String() > srs[j].String()) {
return true
}
}
return false
}
func (srs SecurityRuleSet) AllowList() secrules.SecurityRuleSet {
func (srs SecurityRuleSet) CanBeSplitByProtocol() bool {
firstNormalRuleIndex, find := 0, false
for idx, r := range srs {
if !(strings.HasSuffix(r.String(), "allow any") || strings.HasSuffix(r.String(), "deny any")) && !find {
firstNormalRuleIndex = idx
find = true
} else {
if r.ExternalId == DEFAULT_SRC_RULE_ID || r.ExternalId == DEFAULT_DEST_RULE_ID {
return true
}
if idx > firstNormalRuleIndex {
return false
}
}
}
return true
}
func (srs SecurityRuleSet) AllowList() (secrules.SecurityRuleSet, bool) {
rules := secrules.SecurityRuleSet{}
isOk := true
for _, r := range srs {
if len(r.PeerSecgroupId) > 0 {
isOk = false
}
rules = append(rules, r.SecurityRule)
}
return rules.AllowList()
return rules.AllowList(), isOk
}
func (srs SecurityRuleSet) Debug() {
for i := 0; i < len(srs); i++ {
log.Debugf("Name: %s id: %s external_id: %s priority: %d %s", srs[i].Name, srs[i].Id, srs[i].ExternalId, srs[i].Priority, srs[i].String())
log.Debugf("Name: %s id: %s external_id: %s min: %d max: %d priority: %d %s", srs[i].Name, srs[i].Id, srs[i].ExternalId, srs[i].minPriority, srs[i].maxPriority, srs[i].Priority, srs[i].String())
}
}
func SortSecurityRule(rules SecurityRuleSet, max, min int, isAsc, onlyAllowRules bool) {
if (max >= min || onlyAllowRules) && !isAsc {
sort.Sort(sort.Reverse(rules))
func SortSecurityRule(rules SecurityRuleSet, isAsc bool, info SecRuleInfo) {
if (info.MaxPriority > info.MinPriority && isAsc) || (info.MaxPriority < info.MinPriority && !isAsc) || (info.IsOnlySupportAllowRules && isAsc) {
sort.Sort(rules)
return
}
sort.Sort(rules)
sort.Sort(sort.Reverse(rules))
return
}
@@ -183,103 +264,125 @@ func isAllowListEqual(src, dest secrules.SecurityRuleSet) bool {
return s1.IsEqual(s2)
}
func isPeerListEqual(src, dest SecurityRuleSet) bool {
if len(src) != len(dest) {
return false
}
s1, s2 := set.New(set.ThreadSafe), set.New(set.ThreadSafe)
for i := 0; i < len(src); i++ {
s1.Add(src[i].String())
s2.Add(dest[i].String())
}
return s1.IsEqual(s2)
}
func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, inDels, outDels SecurityRuleSet) {
srcInRules, srcOutRules, isSrcStandardRules := src.Rules.Split(src.IsSupportPeerSecgroup)
destInRules, destOutRules, isDestStandardRules := dest.Rules.Split(dest.IsSupportPeerSecgroup)
srcInRules, srcOutRules := src.Split()
destInRules, destOutRules := dest.Split()
srcInRules, srcOutRules = src.AddDefaultRule(dest, srcInRules, srcOutRules, true)
destInRules, destOutRules = dest.AddDefaultRule(src, destInRules, destOutRules, false)
if debug {
log.Debugf("src in rules: ")
srcInRules.Debug()
// AllowList 需要优先级从高到低排序
SortSecurityRule(srcInRules, false, src)
SortSecurityRule(srcOutRules, false, src)
SortSecurityRule(destInRules, false, dest)
SortSecurityRule(destOutRules, false, dest)
isInAllowSplit := srcInRules.CanBeSplitByProtocol() && destInRules.CanBeSplitByProtocol()
isOutAllowSplit := srcOutRules.CanBeSplitByProtocol() && destOutRules.CanBeSplitByProtocol()
srcInAllowList, srcInOk := srcInRules.AllowList()
srcOutAllowList, srcOutOk := srcOutRules.AllowList()
destInAllowList, destInOk := destInRules.AllowList()
destOutAllowList, destOutOk := destOutRules.AllowList()
inEquals, outEquals, inOk, outOk := isAllowListEqual(srcInAllowList, destInAllowList), isAllowListEqual(srcOutAllowList, destOutAllowList), srcInOk && destInOk, srcOutOk && destOutOk
if inEquals && outEquals && inOk && outOk {
common = dest.rules
return
}
if (isSrcStandardRules && isDestStandardRules) || (!src.IsSupportPeerSecgroup && !dest.IsSupportPeerSecgroup) {
// AllowList 需要优先级从高到低排序
SortSecurityRule(srcInRules, src.MaxPriority, src.MinPriority, false, src.IsOnlySupportAllowRules)
SortSecurityRule(srcOutRules, src.MaxPriority, src.MinPriority, false, src.IsOnlySupportAllowRules)
if debug {
log.Debugf("====desc sort====")
log.Debugf("src in rules: ")
srcInRules.Debug()
log.Debugf("src out rules: ")
srcOutRules.Debug()
log.Debugf("dest in rules: ")
destInRules.Debug()
log.Debugf("dest out rules: ")
destOutRules.Debug()
log.Debugf("====desc sort end====")
SortSecurityRule(destInRules, dest.MaxPriority, dest.MinPriority, false, dest.IsOnlySupportAllowRules)
SortSecurityRule(destOutRules, dest.MaxPriority, dest.MinPriority, false, dest.IsOnlySupportAllowRules)
log.Debugf("isInAllowSplit: %v isOutAllowSplit: %v", isInAllowSplit, isOutAllowSplit)
srcInAllowList := srcInRules.AllowList()
srcOutAllowList := srcOutRules.AllowList()
log.Debugf("AllowList:")
log.Debugf("In: src: %s dest: %s isEquals: %v", srcInAllowList.String(), destInAllowList.String(), inEquals)
log.Debugf("Out: src: %s dest: %s isEquals: %v", srcOutAllowList.String(), destOutAllowList.String(), outEquals)
}
destInAllowList := destInRules.AllowList()
destOutAllowList := destOutRules.AllowList()
inEquals, outEquals := isAllowListEqual(srcInAllowList, destInAllowList), isAllowListEqual(srcOutAllowList, destOutAllowList)
if inEquals && outEquals {
return
}
if debug {
log.Debugf("In: src: %s dest: %s result: %v", srcInAllowList.String(), destInAllowList.String(), inEquals)
log.Debugf("Out: src: %s dest: %s result: %v", srcOutAllowList.String(), destOutAllowList.String(), outEquals)
}
var tryUseAllowList = func(defaultRule SecurityRule, allowList secrules.SecurityRuleSet, rules SecurityRuleSet, isOnlyAllowList bool) SecurityRuleSet {
if len(allowList) < len(rules) || isOnlyAllowList {
rules = SecurityRuleSet{}
for i := range allowList {
rule := SecurityRule{}
rule.SecurityRule = allowList[i]
rules = append(rules, rule)
}
if !utils.IsInStringArray(allowList.String(), []string{
"",
"in:allow any",
"out:allow any",
"in:deny any",
"out:deny any",
}) && strings.HasSuffix(defaultRule.SecurityRule.String(), "deny any") {
rules = append(rules, defaultRule)
}
var tryUseAllowList = func(defaultRule SecurityRule, allowList secrules.SecurityRuleSet, rules SecurityRuleSet, isOnlyAllowList bool, isOk bool) SecurityRuleSet {
if isOk && (len(allowList) < len(rules) || isOnlyAllowList) {
rules = SecurityRuleSet{}
for i := range allowList {
rule := SecurityRule{}
rule.SecurityRule = allowList[i]
rules = append(rules, rule)
}
return rules
}
srcInRules = tryUseAllowList(src.InDefaultRule, srcInAllowList, srcInRules, dest.IsOnlySupportAllowRules)
srcOutRules = tryUseAllowList(src.OutDefaultRule, srcOutAllowList, srcOutRules, dest.IsOnlySupportAllowRules)
if inEquals {
srcInRules, destInRules = []SecurityRule{}, []SecurityRule{}
}
if outEquals {
srcOutRules, destOutRules = []SecurityRule{}, []SecurityRule{}
if !utils.IsInStringArray(allowList.String(), []string{
"",
"in:allow any",
"out:allow any",
"in:deny any",
"out:deny any",
}) && strings.HasSuffix(defaultRule.SecurityRule.String(), "deny any") {
rules = append(rules, defaultRule)
}
}
return rules
}
if debug {
log.Debugf("src in rules: ")
srcInRules.Debug()
srcInRules = tryUseAllowList(src.InDefaultRule, srcInAllowList, srcInRules, dest.IsOnlySupportAllowRules, inOk)
srcOutRules = tryUseAllowList(src.OutDefaultRule, srcOutAllowList, srcOutRules, dest.IsOnlySupportAllowRules, outOk)
if inEquals && inOk {
common = append(common, dest.in...)
srcInRules, destInRules = []SecurityRule{}, []SecurityRule{}
}
if outEquals && outOk {
common = append(common, dest.out...)
srcOutRules, destOutRules = []SecurityRule{}, []SecurityRule{}
}
// 默认从优先级低到高比较
SortSecurityRule(srcInRules, src.MaxPriority, src.MinPriority, true, src.IsOnlySupportAllowRules)
SortSecurityRule(srcOutRules, src.MaxPriority, src.MinPriority, true, src.IsOnlySupportAllowRules)
SortSecurityRule(srcInRules, true, src)
SortSecurityRule(srcOutRules, true, src)
SortSecurityRule(destInRules, dest.MaxPriority, dest.MinPriority, true, dest.IsOnlySupportAllowRules)
SortSecurityRule(destOutRules, dest.MaxPriority, dest.MinPriority, true, dest.IsOnlySupportAllowRules)
SortSecurityRule(destInRules, true, dest)
SortSecurityRule(destOutRules, true, dest)
var addPriority = func(priority int, min, max int, onlyAllowRules bool) int {
if onlyAllowRules {
return priority
}
inc := 1
if max < min {
max, min, inc = min, max, -1
}
if priority >= max || priority <= min {
return priority
}
return priority + inc
if debug {
log.Debugf("====asc sort====")
log.Debugf("src in rules: ")
srcInRules.Debug()
log.Debugf("src out rules: ")
srcOutRules.Debug()
log.Debugf("dest in rules: ")
destInRules.Debug()
log.Debugf("dest out rules: ")
destOutRules.Debug()
log.Debugf("====asc sort end====")
}
var _compare = func(srcRules SecurityRuleSet, destRules SecurityRuleSet) (common, add, del SecurityRuleSet) {
i, j, priority := 0, 0, (dest.MinPriority-1+dest.MaxPriority)/2
i, j, priority := 0, 0, dest.MinPriority
if len(destRules) > 0 && (destRules[i].ExternalId != DEFAULT_DEST_RULE_ID) {
priority = destRules[0].Priority
}
for i < len(srcRules) || j < len(destRules) {
if i < len(srcRules) && j < len(destRules) {
destRuleStr := destRules[j].String()
@@ -302,8 +405,20 @@ func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, i
del = append(del, destRules[j])
j++
} else {
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority, dest.IsOnlySupportAllowRules)
offset := 0
if !dest.IsOnlySupportAllowRules && i-1 >= 0 && srcRules[i-1].Priority != srcRules[i].Priority {
priority, offset = dest.getOffest(priority)
}
if offset != 0 {
for r := range add {
add[r].addPriority(offset)
}
for r := range common {
common[r].addPriority(offset)
}
}
srcRules[i].Priority = priority
srcRules[i].minPriority, srcRules[i].maxPriority = dest.MinPriority, dest.MaxPriority
add = append(add, srcRules[i])
i++
}
@@ -311,8 +426,20 @@ func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, i
del = append(del, destRules[j])
j++
} else if j >= len(destRules) {
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority, dest.IsOnlySupportAllowRules)
offset := 0
if !dest.IsOnlySupportAllowRules && i-1 >= 0 && srcRules[i-1].Priority != srcRules[i].Priority {
priority, offset = dest.getOffest(priority)
}
srcRules[i].Priority = priority
srcRules[i].minPriority, srcRules[i].maxPriority = dest.MinPriority, dest.MaxPriority
if offset != 0 {
for r := range add {
add[r].addPriority(offset)
}
for r := range common {
common[r].addPriority(offset)
}
}
add = append(add, srcRules[i])
i++
}
@@ -365,8 +492,16 @@ func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, i
}
var inCommon, outCommon SecurityRuleSet
inCommon, inAdds, inDels = compare(srcInRules, destInRules)
outCommon, outAdds, outDels = compare(srcOutRules, destOutRules)
if isInAllowSplit {
inCommon, inAdds, inDels = compare(srcInRules, destInRules)
} else {
inCommon, inAdds, inDels = _compare(srcInRules, destInRules)
}
if isOutAllowSplit {
outCommon, outAdds, outDels = compare(srcOutRules, destOutRules)
} else {
outCommon, outAdds, outDels = _compare(srcOutRules, destOutRules)
}
var handleDefaultRules = func(removed, added []SecurityRule, isOnlyAllowList bool) ([]SecurityRule, []SecurityRule) {
ret := []SecurityRule{}
@@ -408,7 +543,8 @@ func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, i
inDels, inAdds = handleDefaultRules(inDels, inAdds, dest.IsOnlySupportAllowRules)
outDels, outAdds = handleDefaultRules(outDels, outAdds, dest.IsOnlySupportAllowRules)
common, _ = handleDefaultRules(append(inCommon, outCommon...), []SecurityRule{}, dest.IsOnlySupportAllowRules)
_common, _ := handleDefaultRules(append(inCommon, outCommon...), []SecurityRule{}, dest.IsOnlySupportAllowRules)
common = append(common, _common...)
return
}