/
policies_for_service.go
107 lines (101 loc) · 4.06 KB
/
policies_for_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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"
)
// getReferredPoliciesForService returns the list of policies that refer to the service.
func (r *defaultPolicyReferenceResolver) getReferredPoliciesForService(ctx context.Context, svc, svcOld *corev1.Service) ([]networking.NetworkPolicy, error) {
if k8s.IsServiceHeadless(svc) {
r.logger.Info("Ignoring headless service", "svc", k8s.NamespacedName(svc))
return nil, nil
}
policiesWithEgressRules := r.policyTracker.GetPoliciesWithEgressRules()
potentialMatches := sets.Set[types.NamespacedName]{}
for pol := range policiesWithEgressRules {
if pol.Namespace == svc.Namespace {
potentialMatches.Insert(pol)
}
}
namespacedPoliciesSet := r.policyTracker.GetPoliciesWithNamespaceReferences()
potentialMatches = potentialMatches.Union(policiesWithEgressRules.Intersection(namespacedPoliciesSet))
r.logger.V(1).Info("Potential matches", "policies", potentialMatches.UnsortedList(), "svc", k8s.NamespacedName(svc))
var networkPolicyList []networking.NetworkPolicy
for policyRef := range potentialMatches {
r.logger.V(1).Info("Checking policy", "reference", policyRef)
policy := &networking.NetworkPolicy{}
if err := r.k8sClient.Get(ctx, policyRef, 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", policyRef)
continue
}
if r.isServiceReferredOnEgress(ctx, svc, policy) {
networkPolicyList = append(networkPolicyList, *policy)
continue
}
if svcOld != nil && r.isServiceReferredOnEgress(ctx, svcOld, policy) {
networkPolicyList = append(networkPolicyList, *policy)
}
}
return networkPolicyList, nil
}
// isServiceReferredOnEgress returns true if the service is referred in the policy
func (r *defaultPolicyReferenceResolver) isServiceReferredOnEgress(ctx context.Context, svc *corev1.Service, policy *networking.NetworkPolicy) bool {
for _, egressRule := range policy.Spec.Egress {
for _, peer := range egressRule.To {
r.logger.V(1).Info("Checking peer for service reference on egress", "peer", peer)
if peer.PodSelector != nil || peer.NamespaceSelector != nil {
if r.isServiceMatchLabelSelector(ctx, svc, &peer, policy.Namespace) {
return true
}
}
}
}
return false
}
// isServiceMatchLabelSelector returns true if the service is referred in the list of peers
func (r *defaultPolicyReferenceResolver) isServiceMatchLabelSelector(ctx context.Context, svc *corev1.Service, peer *networking.NetworkPolicyPeer, policyNamespace string) bool {
if peer.NamespaceSelector != nil {
ns := &corev1.Namespace{}
if err := r.k8sClient.Get(ctx, types.NamespacedName{Name: svc.Namespace}, ns); err != nil {
r.logger.Info("Failed to get namespace", "namespace", svc.Namespace, "err", err)
return false
}
nsSelector, err := metav1.LabelSelectorAsSelector(peer.NamespaceSelector)
if err != nil {
r.logger.Info("Failed to convert namespace selector to selector", "namespace", peer.NamespaceSelector, "err", err)
return false
}
if !nsSelector.Matches(labels.Set(ns.Labels)) {
return false
}
if peer.PodSelector == nil {
return true
}
} else if svc.Namespace != policyNamespace {
r.logger.V(1).Info("Svc and policy namespace does not match", "namespace", svc.Namespace)
return false
}
if svc.Spec.Selector == nil {
r.logger.V(1).Info("Ignoring service without selector", "service", k8s.NamespacedName(svc))
return false
}
svcSelector, err := metav1.LabelSelectorAsSelector(peer.PodSelector)
if err != nil {
r.logger.Info("Failed to convert pod selector to selector", "podSelector", peer.PodSelector, "err", err)
return false
}
if svcSelector.Matches(labels.Set(svc.Spec.Selector)) {
return true
}
return false
}