@@ -17,13 +17,16 @@ package controllers
1717import (
1818 "context"
1919 "fmt"
20+ "slices"
2021
2122 resources "github.com/cryostatio/cryostat-operator/internal/controllers/common/resource_definitions"
2223 "github.com/cryostatio/cryostat-operator/internal/controllers/constants"
2324 "github.com/cryostatio/cryostat-operator/internal/controllers/model"
25+ corev1 "k8s.io/api/core/v1"
2426 networkingv1 "k8s.io/api/networking/v1"
2527 "k8s.io/apimachinery/pkg/api/errors"
2628 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+ "k8s.io/apimachinery/pkg/types"
2730 "k8s.io/apimachinery/pkg/util/intstr"
2831 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2932)
@@ -44,68 +47,158 @@ func installationNamespaceSelector(cr *model.CryostatInstance) *metav1.LabelSele
4447 return namespaceOriginSelector (cr .InstallNamespace )
4548}
4649
50+ const NAMESPACE_NAME_LABEL = "kubernetes.io/metadata.name"
51+
4752func namespaceOriginSelector (namespace string ) * metav1.LabelSelector {
4853 return & metav1.LabelSelector {
4954 MatchLabels : map [string ]string {
50- "kubernetes.io/metadata.name" : namespace ,
55+ NAMESPACE_NAME_LABEL : namespace ,
5156 },
5257 }
5358}
5459
5560func (r * Reconciler ) reconcileCoreNetworkPolicy (ctx context.Context , cr * model.CryostatInstance ) error {
61+ var err error
62+
5663 ingressPolicy := & networkingv1.NetworkPolicy {
5764 ObjectMeta : metav1.ObjectMeta {
5865 Name : fmt .Sprintf ("%s-internal-ingress" , cr .Name ),
5966 Namespace : cr .InstallNamespace ,
6067 },
6168 }
62- if cr .Spec .NetworkPolicies != nil && cr .Spec .NetworkPolicies .CoreConfig != nil && cr .Spec .NetworkPolicies .CoreConfig .IngressDisabled != nil && * cr .Spec .NetworkPolicies .CoreConfig .IngressDisabled {
63- return r .deletePolicy (ctx , ingressPolicy )
69+ ingressDisabled := cr .Spec .NetworkPolicies != nil && cr .Spec .NetworkPolicies .CoreConfig != nil && cr .Spec .NetworkPolicies .CoreConfig .IngressDisabled != nil && * cr .Spec .NetworkPolicies .CoreConfig .IngressDisabled
70+ if ingressDisabled {
71+ err = r .deletePolicy (ctx , ingressPolicy )
72+ }
73+ if err != nil {
74+ return err
6475 }
6576
66- return r .createOrUpdatePolicy (ctx , ingressPolicy , cr .Object , func () error {
67- ingressPolicy .Spec = networkingv1.NetworkPolicySpec {
68- PodSelector : metav1.LabelSelector {
69- MatchLabels : resources .CorePodLabels (cr ),
70- },
71- Ingress : []networkingv1.NetworkPolicyIngressRule {
72- // allow ingress to the authproxy/cryostat HTTP(S) port from any namespace or from the Route
73- {
74- From : []networkingv1.NetworkPolicyPeer {
75- AllNamespacesSelector ,
76- RouteSelector ,
77- },
78- Ports : []networkingv1.NetworkPolicyPort {
79- {
80- Port : & intstr.IntOrString {IntVal : constants .AuthProxyHttpContainerPort },
77+ egressPolicy := & networkingv1.NetworkPolicy {
78+ ObjectMeta : metav1.ObjectMeta {
79+ Name : fmt .Sprintf ("%s-internal-egress" , cr .Name ),
80+ Namespace : cr .InstallNamespace ,
81+ },
82+ }
83+ egressEnabled := cr .Spec .NetworkPolicies != nil && cr .Spec .NetworkPolicies .CoreConfig != nil && cr .Spec .NetworkPolicies .CoreConfig .EgressEnabled != nil && * cr .Spec .NetworkPolicies .CoreConfig .EgressEnabled
84+ if ! egressEnabled {
85+ err = r .deletePolicy (ctx , egressPolicy )
86+ }
87+ if err != nil {
88+ return err
89+ }
90+
91+ if ! ingressDisabled {
92+ err = r .createOrUpdatePolicy (ctx , ingressPolicy , cr .Object , func () error {
93+ ingressPolicy .Spec = networkingv1.NetworkPolicySpec {
94+ PolicyTypes : []networkingv1.PolicyType {networkingv1 .PolicyTypeIngress },
95+ PodSelector : metav1.LabelSelector {
96+ MatchLabels : resources .CorePodLabels (cr ),
97+ },
98+ Ingress : []networkingv1.NetworkPolicyIngressRule {
99+ // allow ingress to the authproxy/cryostat HTTP(S) port from any namespace or from the Route
100+ {
101+ From : []networkingv1.NetworkPolicyPeer {
102+ AllNamespacesSelector ,
103+ RouteSelector ,
104+ },
105+ Ports : []networkingv1.NetworkPolicyPort {
106+ {
107+ Port : & intstr.IntOrString {IntVal : constants .AuthProxyHttpContainerPort },
108+ },
81109 },
82110 },
83- },
84- // allow ingress to the agent gateway from the target namespaces
85- {
86- From : []networkingv1. NetworkPolicyPeer {
87- {
88- NamespaceSelector : & metav1.LabelSelector {
89- MatchExpressions : []metav1. LabelSelectorRequirement {
90- {
91- Key : "kubernetes.io/metadata.name" ,
92- Operator : metav1 . LabelSelectorOpIn ,
93- Values : cr . Spec . TargetNamespaces ,
111+ // allow ingress to the agent gateway from the target namespaces
112+ {
113+ From : []networkingv1. NetworkPolicyPeer {
114+ {
115+ NamespaceSelector : & metav1. LabelSelector {
116+ MatchExpressions : [] metav1.LabelSelectorRequirement {
117+ {
118+ Key : "kubernetes.io/metadata.name" ,
119+ Operator : metav1 . LabelSelectorOpIn ,
120+ Values : cr . Spec . TargetNamespaces ,
121+ } ,
94122 },
95123 },
96124 },
97125 },
98- },
99- Ports : [] networkingv1.NetworkPolicyPort {
100- networkingv1. NetworkPolicyPort {
101- Port : & intstr. IntOrString { IntVal : constants . AgentProxyContainerPort },
126+ Ports : []networkingv1. NetworkPolicyPort {
127+ networkingv1.NetworkPolicyPort {
128+ Port : & intstr. IntOrString { IntVal : constants . AgentProxyContainerPort },
129+ },
102130 },
103131 },
104132 },
133+ }
134+ return nil
135+ })
136+ }
137+ if err != nil {
138+ return err
139+ }
140+
141+ if egressEnabled {
142+ egressDestinations := []networkingv1.NetworkPolicyPeer {}
143+ egressNamespaces := []string {
144+ // allow outgoing connections to Pods in infrastructure namespaces for discovery and auth
145+ "default" ,
146+ "kube-system" ,
147+ // allow outgoing connections to Pods in the InstallNamespace, so Cryostat can connect to its database, storage, etc.
148+ cr .InstallNamespace ,
149+ }
150+ if r .IsOpenShift {
151+ egressNamespaces = append (egressNamespaces , "openshift" )
152+ }
153+ for _ , ns := range cr .TargetNamespaces {
154+ // allow outgoing connections to any Pod in the TargetNamespaces
155+ egressNamespaces = append (egressNamespaces , ns )
156+ }
157+ slices .Sort (egressNamespaces )
158+ egressDestinations = append (egressDestinations , networkingv1.NetworkPolicyPeer {
159+ NamespaceSelector : & metav1.LabelSelector {
160+ MatchExpressions : []metav1.LabelSelectorRequirement {
161+ metav1.LabelSelectorRequirement {
162+ Key : NAMESPACE_NAME_LABEL ,
163+ Operator : metav1 .LabelSelectorOpIn ,
164+ Values : slices .Compact (egressNamespaces ),
165+ },
166+ },
105167 },
168+ })
169+ k8sApiEndpoint := corev1.Endpoints {}
170+ err = r .Client .Get (ctx , types.NamespacedName {Namespace : "default" , Name : "kubernetes" }, & k8sApiEndpoint )
171+ if err != nil {
172+ return err
106173 }
107- return nil
108- })
174+ if len (k8sApiEndpoint .Subsets ) > 0 && len (k8sApiEndpoint .Subsets [0 ].Addresses ) > 0 {
175+ // allow outgoing connections to the Kubernetes API server
176+ egressDestinations = append (egressDestinations ,
177+ networkingv1.NetworkPolicyPeer {
178+ IPBlock : & networkingv1.IPBlock {
179+ CIDR : fmt .Sprintf ("%s/32" , k8sApiEndpoint .Subsets [0 ].Addresses [0 ].IP ),
180+ },
181+ },
182+ )
183+ } else {
184+ return fmt .Errorf ("Endpoints 'kubernetes' had no .Subsets or subset .Addresses" )
185+ }
186+ err = r .createOrUpdatePolicy (ctx , egressPolicy , cr .Object , func () error {
187+ egressPolicy .Spec = networkingv1.NetworkPolicySpec {
188+ PolicyTypes : []networkingv1.PolicyType {networkingv1 .PolicyTypeEgress },
189+ PodSelector : metav1.LabelSelector {
190+ MatchLabels : resources .CorePodLabels (cr ),
191+ },
192+ Egress : []networkingv1.NetworkPolicyEgressRule {
193+ {
194+ To : egressDestinations ,
195+ },
196+ },
197+ }
198+ return nil
199+ })
200+ }
201+ return err
109202}
110203
111204func (r * Reconciler ) reconcileDatabaseNetworkPolicy (ctx context.Context , cr * model.CryostatInstance ) error {
@@ -121,6 +214,7 @@ func (r *Reconciler) reconcileDatabaseNetworkPolicy(ctx context.Context, cr *mod
121214
122215 return r .createOrUpdatePolicy (ctx , ingressPolicy , cr .Object , func () error {
123216 ingressPolicy .Spec = networkingv1.NetworkPolicySpec {
217+ PolicyTypes : []networkingv1.PolicyType {networkingv1 .PolicyTypeIngress },
124218 PodSelector : metav1.LabelSelector {
125219 MatchLabels : resources .DatabasePodLabels (cr ),
126220 },
@@ -159,6 +253,7 @@ func (r *Reconciler) reconcileStorageNetworkPolicy(ctx context.Context, cr *mode
159253
160254 return r .createOrUpdatePolicy (ctx , ingressPolicy , cr .Object , func () error {
161255 ingressPolicy .Spec = networkingv1.NetworkPolicySpec {
256+ PolicyTypes : []networkingv1.PolicyType {networkingv1 .PolicyTypeIngress },
162257 PodSelector : metav1.LabelSelector {
163258 MatchLabels : resources .StoragePodLabels (cr ),
164259 },
@@ -197,6 +292,7 @@ func (r *Reconciler) reconcileReportsNetworkPolicy(ctx context.Context, cr *mode
197292
198293 return r .createOrUpdatePolicy (ctx , ingressPolicy , cr .Object , func () error {
199294 ingressPolicy .Spec = networkingv1.NetworkPolicySpec {
295+ PolicyTypes : []networkingv1.PolicyType {networkingv1 .PolicyTypeIngress },
200296 PodSelector : metav1.LabelSelector {
201297 MatchLabels : resources .ReportsPodLabels (cr ),
202298 },
0 commit comments