Skip to content

fix: wrong ipset name used by ip6tables. #1654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions pkg/controllers/netpol/network_policy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,17 +684,28 @@ func (npc *NetworkPolicyController) cleanupStaleIPSets(activePolicyIPSets map[st
}()
}

for _, ipsets := range npc.ipSetHandlers {
for ipFamily, ipsets := range npc.ipSetHandlers {
cleanupPolicyIPSets := make([]*utils.Set, 0)

if err := ipsets.Save(); err != nil {
klog.Fatalf("failed to initialize ipsets command executor due to %s", err.Error())
}
for _, set := range ipsets.Sets() {
if strings.HasPrefix(set.Name, kubeSourceIPSetPrefix) ||
strings.HasPrefix(set.Name, kubeDestinationIPSetPrefix) {
if _, ok := activePolicyIPSets[set.Name]; !ok {
cleanupPolicyIPSets = append(cleanupPolicyIPSets, set)
if ipFamily == v1core.IPv6Protocol {
for _, set := range ipsets.Sets() {
if strings.HasPrefix(set.Name, fmt.Sprintf("%s:%s", utils.FamillyInet6, kubeSourceIPSetPrefix)) ||
strings.HasPrefix(set.Name, fmt.Sprintf("%s:%s", utils.FamillyInet6, kubeDestinationIPSetPrefix)) {
if _, ok := activePolicyIPSets[set.Name]; !ok {
cleanupPolicyIPSets = append(cleanupPolicyIPSets, set)
}
}
}
} else {
for _, set := range ipsets.Sets() {
if strings.HasPrefix(set.Name, kubeSourceIPSetPrefix) ||
strings.HasPrefix(set.Name, kubeDestinationIPSetPrefix) {
if _, ok := activePolicyIPSets[set.Name]; !ok {
cleanupPolicyIPSets = append(cleanupPolicyIPSets, set)
}
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions pkg/controllers/netpol/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,10 @@ func (npc *NetworkPolicyController) appendRuleToPolicyChain(policyChainName, com
args = append(args, "-m", "comment", "--comment", "\""+comment+"\"")
}
if srcIPSetName != "" {
args = append(args, "-m", "set", "--match-set", srcIPSetName, "src")
args = append(args, "-m", "set", "--match-set", ipSetName(srcIPSetName, ipFamily), "src")
}
if dstIPSetName != "" {
args = append(args, "-m", "set", "--match-set", dstIPSetName, "dst")
args = append(args, "-m", "set", "--match-set", ipSetName(dstIPSetName, ipFamily), "dst")
}
if protocol != "" {
args = append(args, "-p", protocol)
Expand Down Expand Up @@ -904,61 +904,61 @@ func networkPolicyChainName(namespace, policyName string, version string, ipFami
func policySourcePodIPSetName(namespace, policyName string, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + string(ipFamily)))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeSourceIPSetPrefix + encoded[:16]
return ipSetName(kubeSourceIPSetPrefix+encoded[:16], ipFamily)
}

func policyDestinationPodIPSetName(namespace, policyName string, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + string(ipFamily)))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeDestinationIPSetPrefix + encoded[:16]
return ipSetName(kubeDestinationIPSetPrefix+encoded[:16], ipFamily)
}

func policyIndexedSourcePodIPSetName(
namespace, policyName string, ingressRuleNo int, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + "ingressrule" + strconv.Itoa(ingressRuleNo) +
string(ipFamily) + "pod"))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeSourceIPSetPrefix + encoded[:16]
return ipSetName(kubeSourceIPSetPrefix+encoded[:16], ipFamily)
}

func policyIndexedDestinationPodIPSetName(
namespace, policyName string, egressRuleNo int, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + "egressrule" + strconv.Itoa(egressRuleNo) +
string(ipFamily) + "pod"))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeDestinationIPSetPrefix + encoded[:16]
return ipSetName(kubeDestinationIPSetPrefix+encoded[:16], ipFamily)
}

func policyIndexedSourceIPBlockIPSetName(
namespace, policyName string, ingressRuleNo int, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + "ingressrule" + strconv.Itoa(ingressRuleNo) +
string(ipFamily) + "ipblock"))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeSourceIPSetPrefix + encoded[:16]
return ipSetName(kubeSourceIPSetPrefix+encoded[:16], ipFamily)
}

func policyIndexedDestinationIPBlockIPSetName(
namespace, policyName string, egressRuleNo int, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + "egressrule" + strconv.Itoa(egressRuleNo) +
string(ipFamily) + "ipblock"))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeDestinationIPSetPrefix + encoded[:16]
return ipSetName(kubeDestinationIPSetPrefix+encoded[:16], ipFamily)
}

func policyIndexedIngressNamedPortIPSetName(
namespace, policyName string, ingressRuleNo, namedPortNo int, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + "ingressrule" + strconv.Itoa(ingressRuleNo) +
strconv.Itoa(namedPortNo) + string(ipFamily) + "namedport"))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeDestinationIPSetPrefix + encoded[:16]
return ipSetName(kubeDestinationIPSetPrefix+encoded[:16], ipFamily)
}

func policyIndexedEgressNamedPortIPSetName(
namespace, policyName string, egressRuleNo, namedPortNo int, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + "egressrule" + strconv.Itoa(egressRuleNo) +
strconv.Itoa(namedPortNo) + string(ipFamily) + "namedport"))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeDestinationIPSetPrefix + encoded[:16]
return ipSetName(kubeDestinationIPSetPrefix+encoded[:16], ipFamily)
}

func policyRulePortsHasNamedPort(npPorts []networking.NetworkPolicyPort) bool {
Expand Down
87 changes: 87 additions & 0 deletions pkg/controllers/netpol/policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package netpol

import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
)

func testNamePrefix(t *testing.T, testString string, isIPv6 bool) {
if isIPv6 {
assert.Truef(t, strings.HasPrefix(testString, "inet6:"), "%s is IPv6 and should begin with inet6:", testString)
}
}

func Test_policySourcePodIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policySourcePodIPSetName("foo", "bar", v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policySourcePodIPSetName("foo", "bar", v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyDestinationPodIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyDestinationPodIPSetName("foo", "bar", v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyDestinationPodIPSetName("foo", "bar", v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyIndexedSourcePodIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyIndexedSourcePodIPSetName("foo", "bar", 1, v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyIndexedSourcePodIPSetName("foo", "bar", 1, v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyIndexedDestinationPodIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyIndexedDestinationPodIPSetName("foo", "bar", 1, v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyIndexedDestinationPodIPSetName("foo", "bar", 1, v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyIndexedSourceIPBlockIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyIndexedSourceIPBlockIPSetName("foo", "bar", 1, v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyIndexedSourceIPBlockIPSetName("foo", "bar", 1, v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyIndexedDestinationIPBlockIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyIndexedDestinationIPBlockIPSetName("foo", "bar", 1, v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyIndexedDestinationIPBlockIPSetName("foo", "bar", 1, v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyIndexedIngressNamedPortIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyIndexedIngressNamedPortIPSetName("foo", "bar", 1, 1, v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyIndexedIngressNamedPortIPSetName("foo", "bar", 1, 1, v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}

func Test_policyIndexedEgressNamedPortIPSetName(t *testing.T) {
t.Run("Check IPv4 and IPv6 names are correct", func(t *testing.T) {
setName := policyIndexedEgressNamedPortIPSetName("foo", "bar", 1, 1, v1.IPv4Protocol)
testNamePrefix(t, setName, false)
setName = policyIndexedEgressNamedPortIPSetName("foo", "bar", 1, 1, v1.IPv6Protocol)
testNamePrefix(t, setName, true)
})
}
8 changes: 8 additions & 0 deletions pkg/controllers/netpol/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,11 @@ func getPodIPForFamily(pod podInfo, ipFamily api.IPFamily) (string, error) {
return "", fmt.Errorf("did not recognize IP Family for pod: %s:%s family: %s", pod.namespace, pod.name,
ipFamily)
}

func ipSetName(setName string, ipFamily api.IPFamily) string {
if ipFamily == api.IPv4Protocol {
return utils.IPSetName(setName, false)
} else {
return utils.IPSetName(setName, true)
}
}
9 changes: 7 additions & 2 deletions pkg/utils/ipset.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,18 @@ func (set *Set) IsActive() (bool, error) {
return true, nil
}

func (ipset *IPSet) Name(setName string) string {
if ipset.isIpv6 && !strings.HasPrefix(setName, IPv6SetPrefix+":") {
// IPSetName returns the proper set name for this component based upon whether or not it is an IPv6 set
func IPSetName(setName string, isIPv6 bool) string {
if isIPv6 && !strings.HasPrefix(setName, IPv6SetPrefix+":") {
return fmt.Sprintf("%s:%s", IPv6SetPrefix, setName)
}
return setName
}

func (ipset *IPSet) Name(setName string) string {
return IPSetName(setName, ipset.isIpv6)
}

func (set *Set) name() string {
return set.Parent.Name(set.Name)
}
Expand Down