From 75db615d35a362060824ebbec3fbc677fdbfe24c Mon Sep 17 00:00:00 2001 From: Hao Zhou Date: Fri, 15 Mar 2024 21:55:53 +0000 Subject: [PATCH] ignore host network pods in all endpoints --- .github/workflows/pr-tests.yaml | 8 +++- .go-version | 1 + Makefile | 4 +- pkg/resolvers/endpoints.go | 65 +++++++++++++++++++++++---------- pkg/resolvers/endpoints_test.go | 47 ++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 .go-version diff --git a/.github/workflows/pr-tests.yaml b/.github/workflows/pr-tests.yaml index 2b7a004..1ac8718 100644 --- a/.github/workflows/pr-tests.yaml +++ b/.github/workflows/pr-tests.yaml @@ -68,10 +68,14 @@ jobs: timeout-minutes: 5 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: Set variables + run: | + VER=$(cat .go-version) + echo "VERSION=$VER" >> $GITHUB_ENV - uses: actions/setup-go@v4 with: - go-version: '1.21.5' + go-version: ${{ env.VERSION }} cache-dependency-path: "**/go.sum" - name: Install `govulncheck` run: go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/.go-version b/.go-version new file mode 100644 index 0000000..5c9a6fe --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.21.8 \ No newline at end of file diff --git a/Makefile b/Makefile index 1579c6f..4fff67b 100644 --- a/Makefile +++ b/Makefile @@ -172,8 +172,8 @@ mockgen: $(MOCKGEN) $(MOCKGEN): $(LOCALBIN) test -s $(MOCKGEN) || GOBIN=$(LOCALBIN) go install github.com/golang/mock/mockgen@v1.6.0 -GOARCH=amd64 -BUILD_IMAGE=public.ecr.aws/docker/library/golang:1.21.5 +GO_IMAGE_TAG=$(shell cat .go-version) +BUILD_IMAGE=public.ecr.aws/docker/library/golang:$(GO_IMAGE_TAG) BASE_IMAGE=public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-nonroot:latest.2 GO_RUNNER_IMAGE=public.ecr.aws/eks-distro/kubernetes/go-runner:v0.15.0-eks-1-27-3 .PHONY: docker-buildx diff --git a/pkg/resolvers/endpoints.go b/pkg/resolvers/endpoints.go index a56ce80..3441c80 100644 --- a/pkg/resolvers/endpoints.go +++ b/pkg/resolvers/endpoints.go @@ -107,15 +107,17 @@ func (r *defaultEndpointsResolver) computePodSelectorEndpoints(ctx context.Conte if err != nil { return nil, errors.Wrap(err, "unable to get pod selector") } - podList := &corev1.PodList{} - if err := r.k8sClient.List(ctx, podList, &client.ListOptions{ + + podList, err := r.getPodList(ctx, &client.ListOptions{ LabelSelector: podSelector, Namespace: policy.Namespace, - }); err != nil { + }) + + if err != nil { r.logger.Info("Unable to List Pods", "err", err) return nil, err } - for _, pod := range podList.Items { + for _, pod := range podList { podIP := k8s.GetPodIP(&pod) if len(podIP) > 0 { podEndpoints = append(podEndpoints, policyinfo.PodEndpoint{ @@ -200,18 +202,19 @@ func (r *defaultEndpointsResolver) resolveNetworkPeers(ctx context.Context, poli } func (r *defaultEndpointsResolver) getIngressRulesPorts(ctx context.Context, policyNamespace string, policyPodSelector *metav1.LabelSelector, ports []networking.NetworkPolicyPort) []policyinfo.Port { - podList := &corev1.PodList{} - if err := r.k8sClient.List(ctx, podList, &client.ListOptions{ + podList, err := r.getPodList(ctx, &client.ListOptions{ LabelSelector: r.createPodLabelSelector(policyPodSelector), Namespace: policyNamespace, - }); err != nil { + }) + + if err != nil { r.logger.Info("Unable to List Pods", "err", err) return nil } - r.logger.V(2).Info("list pods for ingress", "podList", *podList, "namespace", policyNamespace, "selector", *policyPodSelector) + r.logger.V(2).Info("list pods for ingress", "podList", podList, "namespace", policyNamespace, "selector", *policyPodSelector) var portList []policyinfo.Port - for _, pod := range podList.Items { + for _, pod := range podList { portList = append(portList, r.getPortList(pod, ports)...) r.logger.Info("Got ingress port from pod", "pod", types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}.String()) } @@ -326,17 +329,18 @@ func (r *defaultEndpointsResolver) getMatchingPodAddresses(ctx context.Context, } // populate src pods for ingress and dst pods for egress - podList := &corev1.PodList{} - if err := r.k8sClient.List(ctx, podList, &client.ListOptions{ + podList, err := r.getPodList(ctx, &client.ListOptions{ LabelSelector: r.createPodLabelSelector(ls), Namespace: namespace, - }); err != nil { + }) + if err != nil { r.logger.Info("Unable to List Pods", "err", err) return nil } - r.logger.V(1).Info("Got pods for label selector", "count", len(podList.Items), "selector", ls.String()) - for _, pod := range podList.Items { + r.logger.V(1).Info("Got pods for label selector", "count", len(podList), "selector", ls.String()) + + for _, pod := range podList { podIP := k8s.GetPodIP(&pod) if len(podIP) == 0 { r.logger.Info("pod IP not assigned yet", "pod", k8s.NamespacedName(&pod)) @@ -452,19 +456,21 @@ func (r *defaultEndpointsResolver) getMatchingServicePort(ctx context.Context, s if err != nil { return 0, err } - podList := &corev1.PodList{} - if err := r.k8sClient.List(ctx, podList, &client.ListOptions{ + + podList, err := r.getPodList(ctx, &client.ListOptions{ LabelSelector: podSelector, Namespace: svc.Namespace, - }); err != nil { + }) + if err != nil { r.logger.Info("Unable to List Pods", "err", err) return 0, err } - for i := range podList.Items { - if portVal, err := k8s.LookupListenPortFromPodSpec(svc, &podList.Items[i], *port, protocol); err == nil { + + for i := range podList { + if portVal, err := k8s.LookupListenPortFromPodSpec(svc, &podList[i], *port, protocol); err == nil { return portVal, nil } else { - r.logger.Info("The pod doesn't have port matched", "err", err, "pod", podList.Items[i]) + r.logger.Info("The pod doesn't have port matched", "err", err, "pod", podList[i]) } } return 0, errors.Errorf("unable to find matching service listen port %s for service %s", port.String(), k8s.NamespacedName(svc)) @@ -491,3 +497,22 @@ func dedupPorts(policyPorts []policyinfo.Port) []policyinfo.Port { } return nil } + +func (r *defaultEndpointsResolver) getPodList(ctx context.Context, opts client.ListOption) ([]corev1.Pod, error) { + podList := &corev1.PodList{} + var pods []corev1.Pod + err := r.k8sClient.List(ctx, podList, opts) + if err != nil { + r.logger.Info("Unable to List Pods", "err", err) + } else { + for _, pod := range podList.Items { + if !pod.Spec.HostNetwork { + pods = append(pods, pod) + } else { + r.logger.Info("skipping host network pod", "pod", k8s.NamespacedName(&pod)) + } + } + } + + return pods, err +} diff --git a/pkg/resolvers/endpoints_test.go b/pkg/resolvers/endpoints_test.go index f91b609..bbfb2a6 100644 --- a/pkg/resolvers/endpoints_test.go +++ b/pkg/resolvers/endpoints_test.go @@ -251,6 +251,24 @@ func TestEndpointsResolver_Resolve(t *testing.T) { }, }, } + ingressPolicyOnHostNetwork := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "host-network-policy", + Namespace: "ns", + }, + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networking.NetworkPolicyIngressRule{ + { + From: []networking.NetworkPolicyPeer{ + { + PodSelector: &metav1.LabelSelector{}, + }, + }, + }, + }, + }, + } pod1 := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod1", @@ -278,6 +296,18 @@ func TestEndpointsResolver_Resolve(t *testing.T) { }, }, } + podHostNetwork := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-host-network", + Namespace: "ns", + Annotations: map[string]string{ + "vpc.amazonaws.com/pod-ips": "1.0.0.4", + }, + }, + Spec: corev1.PodSpec{ + HostNetwork: true, + }, + } podNoIP := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod-no-ip", @@ -326,6 +356,23 @@ func TestEndpointsResolver_Resolve(t *testing.T) { {PodIP: "1.0.0.3", Name: "pod3", Namespace: "ns"}, }, }, + { + name: "host network pods should be ignored", + args: args{ + netpol: ingressPolicyOnHostNetwork, + podListCalls: []podListCall{ + { + pods: []corev1.Pod{pod1, podHostNetwork}, + }, + }, + }, + wantIngressEndpoints: []policyinfo.EndpointInfo{ + {CIDR: "1.0.0.1"}, + }, + wantPodEndpoints: []policyinfo.PodEndpoint{ + {PodIP: "1.0.0.1", Name: "pod1", Namespace: "ns"}, + }, + }, { name: "ingress rules", args: args{