pkg/resolvers/policies_for_pod.go (132 lines of code) (raw):
package resolvers
import (
"context"
"github.com/aws/amazon-network-policy-controller-k8s/pkg/k8s"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func (r *defaultPolicyReferenceResolver) getReferredPoliciesForPod(ctx context.Context, pod *corev1.Pod, podOld *corev1.Pod) ([]networking.NetworkPolicy, error) {
policyList := &networking.NetworkPolicyList{}
if err := r.k8sClient.List(ctx, policyList, client.InNamespace(pod.Namespace)); err != nil {
return nil, errors.Wrap(err, "failed to fetch policies")
}
processedPolicies := sets.Set[types.NamespacedName]{}
var referredPolicies []networking.NetworkPolicy
for _, pol := range policyList.Items {
if r.isPodMatchesPolicySelector(pod, podOld, &pol) {
referredPolicies = append(referredPolicies, pol)
processedPolicies.Insert(k8s.NamespacedName(&pol))
continue
}
if r.isPodReferredOnIngressEgress(ctx, pod, &pol) {
referredPolicies = append(referredPolicies, pol)
processedPolicies.Insert(k8s.NamespacedName(&pol))
continue
}
if podOld != nil && r.isPodReferredOnIngressEgress(ctx, podOld, &pol) {
referredPolicies = append(referredPolicies, pol)
processedPolicies.Insert(k8s.NamespacedName(&pol))
}
}
r.logger.V(1).Info("Policies referred on the same namespace", "pod", k8s.NamespacedName(pod),
"policies", referredPolicies)
for _, ref := range r.policyTracker.GetPoliciesWithNamespaceReferences().UnsortedList() {
r.logger.V(1).Info("Policy containing namespace selectors", "ref", ref)
if processedPolicies.Has(ref) {
continue
}
policy := &networking.NetworkPolicy{}
if err := r.k8sClient.Get(ctx, ref, policy); err != nil {
if client.IgnoreNotFound(err) != nil {
return nil, errors.Wrap(err, "failed to get policy")
}
r.logger.V(1).Info("Policy not found", "reference", ref)
continue
}
if r.isPodReferredOnIngressEgress(ctx, pod, policy) {
referredPolicies = append(referredPolicies, *policy)
processedPolicies.Insert(k8s.NamespacedName(policy))
continue
}
if podOld != nil && r.isPodReferredOnIngressEgress(ctx, podOld, policy) {
referredPolicies = append(referredPolicies, *policy)
processedPolicies.Insert(k8s.NamespacedName(policy))
}
}
r.logger.V(1).Info("All referred policies", "pod", k8s.NamespacedName(pod), "policies", referredPolicies)
return referredPolicies, nil
}
func (r *defaultPolicyReferenceResolver) isPodMatchesPolicySelector(pod *corev1.Pod, podOld *corev1.Pod, policy *networking.NetworkPolicy) bool {
ps, err := metav1.LabelSelectorAsSelector(&policy.Spec.PodSelector)
if err != nil {
r.logger.Info("Unable to get pod label selector from policy", "policy", k8s.NamespacedName(policy), "err", err)
return false
}
if ps.Matches(labels.Set(pod.Labels)) {
return true
}
if podOld != nil && ps.Matches(labels.Set(podOld.Labels)) {
return true
}
return false
}
func (r *defaultPolicyReferenceResolver) isPodReferredOnIngressEgress(ctx context.Context, pod *corev1.Pod, policy *networking.NetworkPolicy) bool {
for _, ingRule := range policy.Spec.Ingress {
for _, peer := range ingRule.From {
if r.isPodLabelMatchPeer(ctx, pod, &peer, policy.Namespace) {
return true
}
}
}
for _, egrRule := range policy.Spec.Egress {
for _, peer := range egrRule.To {
if r.isPodLabelMatchPeer(ctx, pod, &peer, policy.Namespace) {
return true
}
}
}
return false
}
func (r *defaultPolicyReferenceResolver) isPodLabelMatchPeer(ctx context.Context, pod *corev1.Pod, peer *networking.NetworkPolicyPeer, policyNamespace string) bool {
if peer.NamespaceSelector != nil {
ns := &corev1.Namespace{}
if err := r.k8sClient.Get(ctx, types.NamespacedName{Name: pod.Namespace}, ns); err != nil {
r.logger.Info("Unable to get namespace", "ns", pod.Namespace, "err", err)
return false
}
nsSelector, err := metav1.LabelSelectorAsSelector(peer.NamespaceSelector)
if err != nil {
r.logger.Info("Unable to get namespace selector", "selector", peer.NamespaceSelector, "err", err)
return false
}
if !nsSelector.Matches(labels.Set(ns.Labels)) {
r.logger.V(1).Info("nsSelector does not match ns labels", "selector", nsSelector,
"ns", ns)
return false
}
if peer.PodSelector == nil {
r.logger.V(1).Info("nsSelector matches ns labels", "selector", nsSelector,
"ns", ns)
return true
}
} else if pod.Namespace != policyNamespace {
r.logger.V(1).Info("Pod and policy namespace mismatch", "pod", k8s.NamespacedName(pod),
"policy ns", policyNamespace)
return false
}
podSelector, err := metav1.LabelSelectorAsSelector(peer.PodSelector)
if err != nil {
r.logger.Info("Unable to get pod selector", "err", err)
return false
}
if podSelector.Matches(labels.Set(pod.Labels)) {
return true
}
return false
}