diff --git a/pkg/netpol/eval/internal/k8s/adminnetpol.go b/pkg/netpol/eval/internal/k8s/adminnetpol.go index 0139e58e..69656ecb 100644 --- a/pkg/netpol/eval/internal/k8s/adminnetpol.go +++ b/pkg/netpol/eval/internal/k8s/adminnetpol.go @@ -145,7 +145,8 @@ func ingressRuleSelectsPeer(rulePeers []apisv1a.AdminNetworkPolicyIngressPeer, s // updateConnsIfEgressRuleSelectsPeer checks if the given dst is selected by given egress rule, // if yes, updates given policyConns with the rule's connections func updateConnsIfEgressRuleSelectsPeer(rulePeers []apisv1a.AdminNetworkPolicyEgressPeer, - rulePorts *[]apisv1a.AdminNetworkPolicyPort, ruleName string, dst Peer, policyConns *PolicyConnections, action string, isBANPrule bool) error { + rulePorts *[]apisv1a.AdminNetworkPolicyPort, ruleName string, dst Peer, policyConns *PolicyConnections, + action string, isBANPrule bool) error { if len(rulePeers) == 0 { return errors.New(netpolerrors.ANPEgressRulePeersErr) } @@ -163,7 +164,8 @@ func updateConnsIfEgressRuleSelectsPeer(rulePeers []apisv1a.AdminNetworkPolicyEg // updateConnsIfIngressRuleSelectsPeer checks if the given src is selected by given ingress rule, // if yes, updates given policyConns with the rule's connections func updateConnsIfIngressRuleSelectsPeer(rulePeers []apisv1a.AdminNetworkPolicyIngressPeer, - rulePorts *[]apisv1a.AdminNetworkPolicyPort, ruleName string, src, dst Peer, policyConns *PolicyConnections, action string, isBANPrule bool) error { + rulePorts *[]apisv1a.AdminNetworkPolicyPort, ruleName string, src, dst Peer, policyConns *PolicyConnections, + action string, isBANPrule bool) error { if len(rulePeers) == 0 { return errors.New(netpolerrors.ANPIngressRulePeersErr) } @@ -311,12 +313,12 @@ func (anp *AdminNetworkPolicy) fullName() string { return types.NamespacedName{Name: anp.Name, Namespace: anp.Namespace}.String() } -func (anp *AdminNetworkPolicy) ruleFullName(ruleName string, isIngress bool) string { - xgress := "Egress" +func ruleFullName(policyName, ruleName string, isIngress bool) string { + xgress := egressName if isIngress { - xgress = "Ingress" + xgress = ingressName } - return anp.fullName() + fmt.Sprintf(" %s rule %s", xgress, ruleName) + return fmt.Sprintf("%s %s rule %s", policyName, xgress, ruleName) } // GetIngressPolicyConns returns the connections from the ingress rules selecting the src in spec of the adminNetworkPolicy @@ -325,7 +327,7 @@ func (anp *AdminNetworkPolicy) GetIngressPolicyConns(src, dst Peer) (*PolicyConn for _, rule := range anp.Spec.Ingress { // rule is apisv1a.AdminNetworkPolicyIngressRule rulePeers := rule.From rulePorts := rule.Ports - if err := updateConnsIfIngressRuleSelectsPeer(rulePeers, rulePorts, anp.ruleFullName(rule.Name, true), + if err := updateConnsIfIngressRuleSelectsPeer(rulePeers, rulePorts, ruleFullName(anp.fullName(), rule.Name, true), src, dst, res, string(rule.Action), false); err != nil { return nil, anp.anpRuleErr(rule.Name, err.Error()) } @@ -339,7 +341,7 @@ func (anp *AdminNetworkPolicy) GetEgressPolicyConns(dst Peer) (*PolicyConnection for _, rule := range anp.Spec.Egress { // rule is apisv1a.AdminNetworkPolicyEgressRule rulePeers := rule.To rulePorts := rule.Ports - if err := updateConnsIfEgressRuleSelectsPeer(rulePeers, rulePorts, anp.ruleFullName(rule.Name, false), + if err := updateConnsIfEgressRuleSelectsPeer(rulePeers, rulePorts, ruleFullName(anp.fullName(), rule.Name, false), dst, res, string(rule.Action), false); err != nil { return nil, anp.anpRuleErr(rule.Name, err.Error()) } diff --git a/pkg/netpol/eval/internal/k8s/baseline_admin_netpol.go b/pkg/netpol/eval/internal/k8s/baseline_admin_netpol.go index f5ee9c66..bbbb144a 100644 --- a/pkg/netpol/eval/internal/k8s/baseline_admin_netpol.go +++ b/pkg/netpol/eval/internal/k8s/baseline_admin_netpol.go @@ -51,21 +51,13 @@ func (banp *BaselineAdminNetworkPolicy) fullName() string { return types.NamespacedName{Name: banp.Name, Namespace: banp.Namespace}.String() } -func (banp *BaselineAdminNetworkPolicy) ruleFullName(ruleName string, isIngress bool) string { - xgress := "Egress" - if isIngress { - xgress = "Ingress" - } - return banp.fullName() + fmt.Sprintf(" %s rule %s", xgress, ruleName) -} - // GetEgressPolicyConns returns the connections from the egress rules selecting the dst in spec of the baselineAdminNetworkPolicy func (banp *BaselineAdminNetworkPolicy) GetEgressPolicyConns(dst Peer) (*PolicyConnections, error) { res := InitEmptyPolicyConnections() for _, rule := range banp.Spec.Egress { // rule is apisv1a.BaselineAdminNetworkPolicyEgressRule rulePeers := rule.To rulePorts := rule.Ports - if err := updateConnsIfEgressRuleSelectsPeer(rulePeers, rulePorts, banp.ruleFullName(rule.Name, false), + if err := updateConnsIfEgressRuleSelectsPeer(rulePeers, rulePorts, ruleFullName(banp.fullName(), rule.Name, false), dst, res, string(rule.Action), true); err != nil { return nil, banpRuleErr(rule.Name, err.Error()) } @@ -79,7 +71,7 @@ func (banp *BaselineAdminNetworkPolicy) GetIngressPolicyConns(src, dst Peer) (*P for _, rule := range banp.Spec.Ingress { // rule is apisv1a.BaselineAdminNetworkPolicyIngressRule rulePeers := rule.From rulePorts := rule.Ports - if err := updateConnsIfIngressRuleSelectsPeer(rulePeers, rulePorts, banp.ruleFullName(rule.Name, true), + if err := updateConnsIfIngressRuleSelectsPeer(rulePeers, rulePorts, ruleFullName(banp.fullName(), rule.Name, true), src, dst, res, string(rule.Action), true); err != nil { return nil, banpRuleErr(rule.Name, err.Error()) } diff --git a/pkg/netpol/eval/internal/k8s/netpol.go b/pkg/netpol/eval/internal/k8s/netpol.go index bc2c1cd6..367e17a6 100644 --- a/pkg/netpol/eval/internal/k8s/netpol.go +++ b/pkg/netpol/eval/internal/k8s/netpol.go @@ -61,8 +61,10 @@ type PolicyExposureWithoutSelectors struct { // if so, also consider concurrent access (or declare not goroutine safe?) const ( - portBase = 10 - portBits = 32 + portBase = 10 + portBits = 32 + egressName = "Egress" + ingressName = "Ingress" ) func getProtocolStr(p *v1.Protocol) string { @@ -110,7 +112,8 @@ func isEmptyPortRange(start, end int32) bool { return start == common.NoPort && end == common.NoPort } -func (np *NetworkPolicy) ruleConnections(rulePorts []netv1.NetworkPolicyPort, dst Peer, ruleIdx int, isIngress bool) (*common.ConnectionSet, error) { +func (np *NetworkPolicy) ruleConnections(rulePorts []netv1.NetworkPolicyPort, dst Peer, + ruleIdx int, isIngress bool) (*common.ConnectionSet, error) { if len(rulePorts) == 0 { res := common.MakeConnectionSet(true) // If this field is empty or missing, this rule matches all ports res.AddCommonImplyingRule(np.ruleName(ruleIdx, isIngress)) @@ -490,9 +493,9 @@ func (np *NetworkPolicy) fullName() string { } func (np *NetworkPolicy) ruleName(ruleIdx int, isIngress bool) string { - xgress := "Egress" + xgress := egressName if isIngress { - xgress = "Ingress" + xgress = ingressName } return np.fullName() + fmt.Sprintf(" %s rule #%d", xgress, ruleIdx) } diff --git a/pkg/netpol/internal/common/augmented_intervalset.go b/pkg/netpol/internal/common/augmented_intervalset.go index 0a950da1..2ce7b0f7 100644 --- a/pkg/netpol/internal/common/augmented_intervalset.go +++ b/pkg/netpol/internal/common/augmented_intervalset.go @@ -70,9 +70,10 @@ func NewAugmentedIntervalWithRules(start, end int64, inSet bool, rules *Implying return AugmentedInterval{interval: interval.New(start, end), inSet: inSet, implyingRules: rules.Copy()} } -// CanonicalSet is a set of int64 integers, implemented using an ordered slice of non-overlapping, non-touching interval -// the intervals should include both included intervals and holes; i.e., start of every interval is the end of a previous interval incremented by 1 -// the last interval should always end with '-1' and should have inSet being false (thus representing a hole till the end of the range) +// AugmentedCanonicalSet is a set of int64 integers, implemented using an ordered slice of non-overlapping, non-touching interval. +// The intervals should include both included intervals and holes; +// i.e., start of every interval is the end of a previous interval incremented by 1. +// The last interval should always end with '-1' and should have inSet being false (thus representing a hole till the end of the range) type AugmentedCanonicalSet struct { intervalSet []AugmentedInterval } @@ -121,7 +122,7 @@ func (c *AugmentedCanonicalSet) CalculateSize() int64 { // nextIncludedInterval finds an interval included in set (not hole), starting from fromInd. // if there are a few continuous in set intervals, it will return the union of all of them. // it returns the found (potentially extended) interval, and the biggest index contributing to the result -func (c *AugmentedCanonicalSet) nextIncludedInterval(fromInd int) (interval.Interval, int) { +func (c *AugmentedCanonicalSet) nextIncludedInterval(fromInd int) (res interval.Interval, index int) { start := fromInd for start < len(c.intervalSet) && !c.intervalSet[start].inSet { start++ @@ -178,8 +179,10 @@ func (c *AugmentedCanonicalSet) AddAugmentedInterval(v AugmentedInterval) { copy(result, set[0:left]) if v.interval.Start() > set[left].interval.Start() && set[left].inSet != v.inSet { // split set[left] into two intervals, while the implying rules of the second interval should get the new value (from v) - new1 := AugmentedInterval{interval: interval.New(set[left].interval.Start(), v.interval.Start()-1), inSet: set[left].inSet, implyingRules: set[left].implyingRules.Copy()} - new2 := AugmentedInterval{interval: interval.New(v.interval.Start(), set[left].interval.End()), inSet: v.inSet, implyingRules: v.implyingRules.Copy()} + new1 := AugmentedInterval{interval: interval.New(set[left].interval.Start(), v.interval.Start()-1), + inSet: set[left].inSet, implyingRules: set[left].implyingRules.Copy()} + new2 := AugmentedInterval{interval: interval.New(v.interval.Start(), set[left].interval.End()), + inSet: v.inSet, implyingRules: v.implyingRules.Copy()} result = append(result, new1, new2) left++ } @@ -246,23 +249,27 @@ func (c *AugmentedCanonicalSet) ContainedIn(other *AugmentedCanonicalSet) bool { otherInterval, otherInd := other.nextIncludedInterval(currOtherInd) if thisInd == -1 { return true // end of this interval set - } else if otherInd == -1 { + } + if otherInd == -1 { return false // end of other interval set, but still have uncovered interval in this set - } else if thisInterval.IsSubset(otherInterval) { + } + if thisInterval.IsSubset(otherInterval) { // this interval is included in other; move to next intervals currThisInd = thisInd + 1 currOtherInd = otherInd + 1 continue - } else if thisInterval.Overlap(otherInterval) { + } + if thisInterval.Overlap(otherInterval) { // only part of this interval is contained return false - } else if thisInterval.End() < otherInterval.Start() { + } + if thisInterval.End() < otherInterval.Start() { // this interval is not contained here return false - } else { // otherInterval.End() < thisInterval.Start() - // increment currOtherInd - currOtherInd = otherInd + 1 } + // otherInterval.End() < thisInterval.Start() + // increment currOtherInd + currOtherInd = otherInd + 1 } return true } @@ -281,11 +288,11 @@ func (c *AugmentedCanonicalSet) Intersect(other *AugmentedCanonicalSet) *Augment if !right.inSet { continue } - interval := left.interval.Intersect(right.interval) - if interval.IsEmpty() { + intersection := left.interval.Intersect(right.interval) + if intersection.IsEmpty() { continue } - toAdd := NewAugmentedInterval(interval.Start(), interval.End(), true) + toAdd := NewAugmentedInterval(intersection.Start(), intersection.End(), true) toAdd.implyingRules = left.implyingRules.Copy() toAdd.implyingRules.Union(right.implyingRules) res.AddAugmentedInterval(toAdd) @@ -306,9 +313,11 @@ func (c *AugmentedCanonicalSet) Overlap(other *AugmentedCanonicalSet) bool { otherInterval, otherInd := other.nextIncludedInterval(currOtherInd) if thisInd == -1 || otherInd == -1 { return false // did not find overlapping interval - } else if thisInterval.Overlap(otherInterval) { + } + if thisInterval.Overlap(otherInterval) { return true - } else if thisInterval.End() < otherInterval.Start() { + } + if thisInterval.End() < otherInterval.Start() { // increment currThisInd currThisInd = thisInd + 1 } else { // otherInterval.End() < thisInterval.Start() @@ -356,8 +365,8 @@ func (c *AugmentedCanonicalSet) Elements() []int64 { return res } -func NewAugmentedSetFromInterval(interval AugmentedInterval) *AugmentedCanonicalSet { +func NewAugmentedSetFromInterval(augInt AugmentedInterval) *AugmentedCanonicalSet { result := NewAugmentedCanonicalSet() - result.AddAugmentedInterval(interval) + result.AddAugmentedInterval(augInt) return result } diff --git a/pkg/netpol/internal/common/connectionset.go b/pkg/netpol/internal/common/connectionset.go index 64c614c4..47d8de23 100644 --- a/pkg/netpol/internal/common/connectionset.go +++ b/pkg/netpol/internal/common/connectionset.go @@ -253,7 +253,8 @@ func (conn *ConnectionSet) GetNamedPorts() map[v1.Protocol]NamedPortsType { // ReplaceNamedPortWithMatchingPortNum : replacing given namedPort with the matching given port num in the connection // if port num is -1; just deletes the named port from the protocol's list -func (conn *ConnectionSet) ReplaceNamedPortWithMatchingPortNum(protocol v1.Protocol, namedPort string, portNum int32, implyingRules *ImplyingRulesType) { +func (conn *ConnectionSet) ReplaceNamedPortWithMatchingPortNum(protocol v1.Protocol, namedPort string, portNum int32, + implyingRules *ImplyingRulesType) { protocolPortSet := conn.AllowedProtocols[protocol] if portNum != NoPort { protocolPortSet.AddPort(intstr.FromInt32(portNum), implyingRules) diff --git a/pkg/netpol/internal/common/portset.go b/pkg/netpol/internal/common/portset.go index 1f483a84..b297b39d 100644 --- a/pkg/netpol/internal/common/portset.go +++ b/pkg/netpol/internal/common/portset.go @@ -34,7 +34,8 @@ func portNames(ports NamedPortsType) []string { type PortSet struct { Ports *AugmentedCanonicalSet // ports, augmented with implying rules data (used for explainability) // NamedPorts/ExcludedNamedPorts is a map from a port name to implying rule names (used for explainnability) - // When not running with explainability, existing (excluded)named ports will be represented by a mapping from a port name to an empty implying rules holder + // When not running with explainability, existing (excluded)named ports will be represented by a mapping + // from a port name to an empty implying rules holder NamedPorts NamedPortsType ExcludedNamedPorts NamedPortsType } @@ -58,7 +59,6 @@ func MakeAllPortSetWithImplyingRules(rules *ImplyingRulesType) *PortSet { NamedPorts: NamedPortsType{}, ExcludedNamedPorts: NamedPortsType{}, } - } // Equal: return true if current object equals another PortSet object