Skip to content

Commit

Permalink
Support podSelector namespaceSelector conversion in SP
Browse files Browse the repository at this point in the history
  • Loading branch information
timdengyun committed Jan 19, 2024
1 parent 15562cd commit 39f6f66
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 243 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ func (r *SecurityPolicyReconciler) Start(mgr ctrl.Manager) error {
return nil
}

// GarbageCollector collect securitypolicy which has been removed from crd.
// GarbageCollector collect securitypolicy which has been removed from k8s.
// cancel is used to break the loop during UT
func (r *SecurityPolicyReconciler) GarbageCollector(cancel chan bool, timeout time.Duration) {
ctx := context.Background()
Expand Down
99 changes: 52 additions & 47 deletions pkg/nsx/services/securitypolicy/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"

"github.com/vmware-tanzu/nsx-operator/pkg/apis/v1alpha1"
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
Expand Down Expand Up @@ -40,16 +41,7 @@ var (
func (service *SecurityPolicyService) buildSecurityPolicy(obj *v1alpha1.SecurityPolicy) (*model.SecurityPolicy, *[]model.Group, *[]ProjectShare, error) {
var nsxRules []model.Rule
var nsxGroups []model.Group
var projectShares []ProjectShare

contains := func(groups []model.Group, group model.Group) bool {
for _, a := range groups {
if *a.Id == *group.Id {
return true
}
}
return false
}
var nsxProjectShares []ProjectShare

log.V(1).Info("building the model SecurityPolicy from CR SecurityPolicy", "object", *obj)
nsxSecurityPolicy := &model.SecurityPolicy{}
Expand All @@ -71,38 +63,57 @@ func (service *SecurityPolicyService) buildSecurityPolicy(obj *v1alpha1.Security
nsxGroups = append(nsxGroups, *policyGroup)
}

currentSet := sets.Set[string]{}
for ruleIdx, r := range obj.Spec.Rules {
rule := r
// A rule containing named port may expand to multiple rules if the name maps to multiple port numbers.
expandRules, ruleGroups, shares, err := service.buildRuleAndGroups(obj, &rule, ruleIdx)
expandRules, ruleGroups, projectShares, err := service.buildRuleAndGroups(obj, &rule, ruleIdx)
if err != nil {
log.Error(err, "failed to build rule and groups", "rule", rule, "ruleIndex", ruleIdx)
return nil, nil, nil, err
}

for _, nsxRule := range expandRules {
if nsxRule != nil {
nsxRules = append(nsxRules, *nsxRule)
if !currentSet.Has(*nsxRule.Id) {
currentSet.Insert(*nsxRule.Id)
nsxRules = append(nsxRules, *nsxRule)
}
}
}
for _, ruleGroup := range ruleGroups {
if ruleGroup != nil {
// If the group is already in the list, skip it.
if !contains(nsxGroups, *ruleGroup) {
nsxGroups = append(nsxGroups, *ruleGroup)

currentSet.Clear()
for _, nsxGroup := range ruleGroups {
if nsxGroup != nil {
if !currentSet.Has(*nsxGroup.Id) {
currentSet.Insert(*nsxGroup.Id)
nsxGroups = append(nsxGroups, *nsxGroup)
}
}
}
for _, share := range shares {
if share != nil {
projectShares = append(projectShares, *share)

currentSet.Clear()
for _, projectShare := range projectShares {
if projectShare != nil {
if !currentSet.Has(*projectShare.share.Id) {
currentSet.Insert(*projectShare.share.Id)
nsxProjectShares = append(nsxProjectShares, *projectShare)
}
}
}

}
nsxSecurityPolicy.Rules = nsxRules
nsxSecurityPolicy.Tags = service.buildBasicTags(obj)
log.V(1).Info("built nsxSecurityPolicy", "nsxSecurityPolicy", nsxSecurityPolicy, "nsxGroups", nsxGroups)
return nsxSecurityPolicy, &nsxGroups, &projectShares, nil
// nsxRules info are included in nsxSecurityPolicy obj
log.Info("built nsxSecurityPolicy", "nsxSecurityPolicy", nsxSecurityPolicy, "nsxGroups", nsxGroups)

for i := len(nsxProjectShares) - 1; i >= 0; i-- {
log.Info("built nsxSecurityPolicy", "projectGroups", *(nsxProjectShares[i].shareGroup),
"projectShares", *(nsxProjectShares[i].share))
}

return nsxSecurityPolicy, &nsxGroups, &nsxProjectShares, nil
}

func (service *SecurityPolicyService) buildPolicyGroup(obj *v1alpha1.SecurityPolicy) (*model.Group, string, error) {
Expand Down Expand Up @@ -138,7 +149,7 @@ func (service *SecurityPolicyService) buildPolicyGroup(obj *v1alpha1.SecurityPol
}
}
log.V(2).Info("build policy target group criteria",
"total criteria", targetGroupCriteriaCount, "total expressions of criteria", targetGroupTotalExprCount)
"totalCriteria", targetGroupCriteriaCount, "totalExprsOfCriteria", targetGroupTotalExprCount)

if targetGroupCriteriaCount > MaxCriteria {
errorMsg = fmt.Sprintf(
Expand All @@ -161,7 +172,7 @@ func (service *SecurityPolicyService) buildPolicyGroup(obj *v1alpha1.SecurityPol
return nil, "", err
}

log.V(1).Info("built policy target group", "policyGroup", policyAppliedGroup)
log.V(1).Info("built policy target group", "policyAppliedGroup", policyAppliedGroup)
return &policyAppliedGroup, policyAppliedGroupPath, nil
}

Expand Down Expand Up @@ -214,7 +225,7 @@ func (service *SecurityPolicyService) buildTargetTags(obj *v1alpha1.SecurityPoli
return targetTags
}

// Todo, use the uitl basic func to generate basic tags
// Todo, use the util basic func to generate basic tags
func (service *SecurityPolicyService) buildBasicTags(obj *v1alpha1.SecurityPolicy) []model.Tag {
tags := []model.Tag{
{
Expand Down Expand Up @@ -359,12 +370,7 @@ func (service *SecurityPolicyService) buildAppliedGroupID(obj *v1alpha1.Security

// build appliedTo group path for both policy and rule levels.
func (service *SecurityPolicyService) buildAppliedGroupPath(obj *v1alpha1.SecurityPolicy, ruleIdx int) (string, error) {
var groupID string
if ruleIdx == -1 {
groupID = service.buildAppliedGroupID(obj, -1)
} else {
groupID = service.buildAppliedGroupID(obj, ruleIdx)
}
groupID := service.buildAppliedGroupID(obj, ruleIdx)

if isVpcEnabled(service) {
vpcInfo, err := getVpcInfo(obj.ObjectMeta.Namespace)
Expand Down Expand Up @@ -432,6 +438,7 @@ func (service *SecurityPolicyService) buildRuleAndGroups(obj *v1alpha1.SecurityP
if err != nil {
return nil, nil, nil, err
}

if nsxRuleSrcGroup != nil {
ruleGroups = append(ruleGroups, nsxRuleSrcGroup)
}
Expand All @@ -448,13 +455,15 @@ func (service *SecurityPolicyService) buildRuleAndGroups(obj *v1alpha1.SecurityP
if err != nil {
return nil, nil, nil, err
}

if nsxRuleDstGroup != nil {
ruleGroups = append(ruleGroups, nsxRuleDstGroup)
}
if nsxProjectShare != nil {
projectShares = append(projectShares, nsxProjectShare)
}
}

nsxRule.SourceGroups = []string{nsxRuleSrcGroupPath}
nsxRule.DestinationGroups = []string{nsxRuleDstGroupPath}

Expand All @@ -470,10 +479,6 @@ func (service *SecurityPolicyService) buildRuleAndGroups(obj *v1alpha1.SecurityP
}
ruleGroups = append(ruleGroups, nsxRuleAppliedGroup)
nsxRule.Scope = []string{nsxRuleAppliedGroupPath}

log.V(1).Info("built rule and groups", "nsxRuleAppliedGroup", nsxRuleAppliedGroup,
"~", nsxRuleSrcGroup, "nsxRuleDstGroup", nsxRuleDstGroup,
"action", *nsxRule.Action, "direction", *nsxRule.Direction)
}
return nsxRules, ruleGroups, projectShares, nil
}
Expand Down Expand Up @@ -505,7 +510,7 @@ func (service *SecurityPolicyService) buildRuleServiceEntries(port v1alpha1.Secu
"overridden": data.NewBooleanValue(false),
},
)
log.V(1).Info("built service entry", "serviceEntry", serviceEntry)
log.V(1).Info("built rule service entry", "destinationPorts", portRange, "protocol", port.Protocol)
return serviceEntry
}

Expand All @@ -529,6 +534,7 @@ func (service *SecurityPolicyService) buildRuleAppliedToGroup(obj *v1alpha1.Secu
return nil, "", err
}
}
log.V(1).Info("built rule target group", "ruleAppliedGroup", nsxRuleAppliedGroup)
return nsxRuleAppliedGroup, nsxRuleAppliedGroupPath, nil
}

Expand Down Expand Up @@ -644,8 +650,8 @@ func (service *SecurityPolicyService) buildRuleAppliedGroupByRule(obj *v1alpha1.
return nil, "", err
}
}
log.V(2).Info("build rule applied group criteria", "total criteria",
ruleGroupCriteriaCount, "total expressions of criteria", ruleGroupTotalExprCount)
log.V(2).Info("build rule applied group criteria", "totalCriteria",
ruleGroupCriteriaCount, "totalExprsOfCriteria", ruleGroupTotalExprCount)

if ruleGroupCriteriaCount > MaxCriteria {
errorMsg = fmt.Sprintf(
Expand Down Expand Up @@ -763,7 +769,7 @@ func (service *SecurityPolicyService) buildRulePeerGroup(obj *v1alpha1.SecurityP
}
}
log.V(2).Info(fmt.Sprintf("build rule %s group criteria", ruleDirection),
"total criteria", rulePeerGroupCriteriaCount, "total expressions of criteria", rulePeerGroupTotalExprCount)
"TotalCriteria", rulePeerGroupCriteriaCount, "totalExprsOfCriteria", rulePeerGroupTotalExprCount)

if rulePeerGroupCriteriaCount > MaxCriteria {
errorMsg = fmt.Sprintf(
Expand Down Expand Up @@ -795,18 +801,17 @@ func (service *SecurityPolicyService) buildRulePeerGroup(obj *v1alpha1.SecurityP

sharedWith, err := service.buildSharedWith(&sharedNamespace)
if err != nil {
log.Error(err, "failed to build SharedWith path", "rule group Name", rulePeerGroupName)
log.Error(err, "failed to build SharedWith path", "ruleGroupName", rulePeerGroupName)
return nil, "", nil, err
}
// Build a nsx share resource in project level
share, err := service.buildProjectShare(obj, &rulePeerGroup, []string{rulePeerGroupPath}, *sharedWith)
nsxShare, err := service.buildProjectShare(obj, &rulePeerGroup, []string{rulePeerGroupPath}, *sharedWith)
if err != nil {
log.Error(err, "failed to build project share", "rule group Name", rulePeerGroupName)
log.Error(err, "failed to build project nsx share", "ruleGroupName", rulePeerGroupName)
return nil, "", nil, err
}

projectShare.share = share
log.V(1).Info("built nsx project share resource", "share", share)
projectShare.share = nsxShare
return nil, rulePeerGroupPath, &projectShare, err
}

Expand Down Expand Up @@ -910,7 +915,7 @@ func (service *SecurityPolicyService) updateTargetExpressions(obj *v1alpha1.Secu
return 0, 0, err
}

log.V(2).Info("update target expressions", "index", ruleIdx)
log.V(2).Info("update target expressions", "ruleIndex", ruleIdx)
service.appendOperatorIfNeeded(&group.Expression, "OR")
expressions := service.buildGroupExpression(&group.Expression)

Expand Down Expand Up @@ -1139,7 +1144,7 @@ func (service *SecurityPolicyService) validateSelectorExpressions(matchLabelsCou

if !mixedCriteria && totalExprCount > MaxCriteriaExpressions {
errorMsg = fmt.Sprintf(
"total count of labelSelectors expressions %d exceed NSX limit of %d in one criteria based on same member type",
"total count of labelSelectors expressions %d exceed NSX limit of %d in one criteria based on the same member type",
totalExprCount,
MaxCriteriaExpressions,
)
Expand Down Expand Up @@ -1349,7 +1354,7 @@ func (service *SecurityPolicyService) updatePeerExpressions(obj *v1alpha1.Securi
group.Expression = append(group.Expression, blockExpression)
}

log.V(2).Info("update peer expressions", "index", ruleIdx)
log.V(2).Info("update peer expressions", "ruleIndex", ruleIdx)
if peer.PodSelector == nil && peer.VMSelector == nil && peer.NamespaceSelector == nil {
return 0, 0, nil
} else if peer.PodSelector != nil && peer.VMSelector != nil && peer.NamespaceSelector == nil {
Expand Down
12 changes: 7 additions & 5 deletions pkg/nsx/services/securitypolicy/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,14 @@ func (share *Share) Value() data.DataValue {
return dataValue
}

func SecurityPolicyToComparable(sp *model.SecurityPolicy) Comparable {
func SecurityPolicyPtrToComparable(sp *model.SecurityPolicy) Comparable {
return (*SecurityPolicy)(sp)
}

func SecurityPolicyToComparable(sp model.SecurityPolicy) Comparable {
return (*SecurityPolicy)(&sp)
}

func RulesPtrToComparable(rules []*model.Rule) []Comparable {
res := make([]Comparable, 0, len(rules))
for i := range rules {
Expand All @@ -104,13 +108,15 @@ func RulesToComparable(rules []model.Rule) []Comparable {
}
return res
}

func GroupsPtrToComparable(groups []*model.Group) []Comparable {
res := make([]Comparable, 0, len(groups))
for i := range groups {
res = append(res, (*Group)((groups[i])))
}
return res
}

func GroupsToComparable(groups []model.Group) []Comparable {
res := make([]Comparable, 0, len(groups))
for i := range groups {
Expand All @@ -119,10 +125,6 @@ func GroupsToComparable(groups []model.Group) []Comparable {
return res
}

func ShareToComparable(share *model.Share) Comparable {
return (*Share)(share)
}

func SharesPtrToComparable(shares []*model.Share) []Comparable {
res := make([]Comparable, 0, len(shares))
for i := range shares {
Expand Down
2 changes: 1 addition & 1 deletion pkg/nsx/services/securitypolicy/compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func TestSecurityPolicyEqual(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isChanged := common.CompareResource(SecurityPolicyToComparable(tt.inputPolicy1), SecurityPolicyToComparable(tt.inputPolicy2))
isChanged := common.CompareResource(SecurityPolicyPtrToComparable(tt.inputPolicy1), SecurityPolicyPtrToComparable(tt.inputPolicy2))
changedSecurityPolicy := tt.inputPolicy2
assert.Equal(t, tt.expectedResult2, isChanged)
assert.Equal(t, tt.expectedResult, changedSecurityPolicy)
Expand Down
6 changes: 3 additions & 3 deletions pkg/nsx/services/securitypolicy/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (service *SecurityPolicyService) expandRuleByService(obj *v1alpha1.Security
log.V(1).Info("built ruleIPSetGroup", "ruleIPSetGroup", ruleIPSetGroup)
nsxGroups = append(nsxGroups, ruleIPSetGroup)
}
log.V(1).Info("built rule by service entry", "rule", nsxRule)
log.V(1).Info("built rule by service entry", "nsxRule", nsxRule)
return nsxGroups, nsxRule, nil
}

Expand Down Expand Up @@ -168,8 +168,8 @@ func (service *SecurityPolicyService) resolvePodPort(pod v1.Pod, spPort *v1alpha
for _, c := range pod.Spec.Containers {
container := c
for _, port := range container.Ports {
log.V(2).Info("resolvePodPort", "namespace", pod.Namespace, "pod_name", pod.Name,
"port_name", port.Name, "containerPort", port.ContainerPort,
log.V(2).Info("resolvePodPort", "namespace", pod.Namespace, "podName", pod.Name,
"portName", port.Name, "containerPort", port.ContainerPort,
"protocol", port.Protocol, "podIP", pod.Status.PodIP)
if port.Name == spPort.Port.String() && port.Protocol == spPort.Protocol {
if pod.Status.Phase != "Running" {
Expand Down
Loading

0 comments on commit 39f6f66

Please sign in to comment.