@@ -330,19 +330,73 @@ func customizeProbeDefaults(config *corev1.Probe, defaultProbe *corev1.Probe) *c
330330 return probe
331331}
332332
333+ func createEgressBypass (ba common.BaseComponent , isOpenShift bool , getDNSEgressRule func (string , string ) (bool , networkingv1.NetworkPolicyEgressRule ), getEndpoints func (string , string ) (* corev1.Endpoints , error )) (bool , []networkingv1.NetworkPolicyEgressRule ) {
334+ egressRules := []networkingv1.NetworkPolicyEgressRule {}
335+
336+ var dnsRule networkingv1.NetworkPolicyEgressRule
337+ var usingPermissiveRule bool
338+ // If allowed, add an Egress rule to access the OpenShift DNS or K8s CoreDNS. Otherwise, use a permissive cluster-wide Egress rule.
339+ if isOpenShift {
340+ usingPermissiveRule , dnsRule = getDNSEgressRule ("dns-default" , "openshift-dns" )
341+ } else {
342+ usingPermissiveRule , dnsRule = getDNSEgressRule ("kube-dns" , "kube-system" )
343+ }
344+ egressRules = append (egressRules , dnsRule )
345+
346+ // If the DNS rule is a specific Egress rule also check if another Egress rule can be created for the API server.
347+ // Otherwise, fallback to a permissive cluster-wide Egress rule.
348+ if ! usingPermissiveRule {
349+ if apiServerEndpoints , err := getEndpoints ("kubernetes" , "default" ); err == nil {
350+ rule := networkingv1.NetworkPolicyEgressRule {}
351+ // Define the port
352+ port := networkingv1.NetworkPolicyPort {}
353+ port .Protocol = & apiServerEndpoints .Subsets [0 ].Ports [0 ].Protocol
354+ var portNumber intstr.IntOrString = intstr .FromInt ((int )(apiServerEndpoints .Subsets [0 ].Ports [0 ].Port ))
355+ port .Port = & portNumber
356+ rule .Ports = append (rule .Ports , port )
357+
358+ // Add the endpoint address as ipBlock entries
359+ for _ , endpoint := range apiServerEndpoints .Subsets {
360+ for _ , address := range endpoint .Addresses {
361+ peer := networkingv1.NetworkPolicyPeer {}
362+ ipBlock := networkingv1.IPBlock {}
363+ ipBlock .CIDR = address .IP + "/32"
364+
365+ peer .IPBlock = & ipBlock
366+ rule .To = append (rule .To , peer )
367+ }
368+ }
369+ egressRules = append (egressRules , rule )
370+ } else {
371+ // The operator couldn't create a rule for the K8s API server so add a permissive Egress rule
372+ rule := networkingv1.NetworkPolicyEgressRule {}
373+ egressRules = append (egressRules , rule )
374+ }
375+ }
376+ return usingPermissiveRule , egressRules
377+ }
378+
333379// createNetworkPolicyEgressRules returns the network policy rules for outgoing traffic to other Pod(s)
334- func createNetworkPolicyEgressRules (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , ba common.BaseComponent ) []networkingv1.NetworkPolicyEgressRule {
380+ func createNetworkPolicyEgressRules (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , isBypassingDenyAllEgress bool , getDNSEgressRule func ( string , string ) ( bool , networkingv1. NetworkPolicyEgressRule ), getEndpoints func ( string , string ) ( * corev1. Endpoints , error ), ba common.BaseComponent ) []networkingv1.NetworkPolicyEgressRule {
335381 config := ba .GetNetworkPolicy ()
382+ egressRules := []networkingv1.NetworkPolicyEgressRule {}
383+ if isBypassingDenyAllEgress {
384+ usingPermissiveRule , bypassRules := createEgressBypass (ba , isOpenShift , getDNSEgressRule , getEndpoints )
385+ egressRules = append (egressRules , bypassRules ... )
386+ if usingPermissiveRule {
387+ return egressRules // exit early because permissive egress is set
388+ }
389+ }
390+ // configure the main application egress rule
336391 var rule networkingv1.NetworkPolicyEgressRule
337-
338392 if config == nil || ((config .GetToNamespaceLabels () != nil && len (config .GetToNamespaceLabels ()) == 0 ) &&
339393 (config .GetToLabels () != nil && len (config .GetToLabels ()) == 0 )) {
340394 rule = createAllowAllNetworkPolicyEgressRule ()
341395 } else {
342396 rule = createNetworkPolicyEgressRule (ba .GetApplicationName (), networkPolicy .Namespace , config )
343397 }
344-
345- return []networkingv1. NetworkPolicyEgressRule { rule }
398+ egressRules = append ( egressRules , rule )
399+ return egressRules
346400}
347401
348402func createNetworkPolicyEgressRule (appName string , namespace string , config common.BaseComponentNetworkPolicy ) networkingv1.NetworkPolicyEgressRule {
@@ -364,7 +418,26 @@ func createAllowAllNetworkPolicyEgressRule() networkingv1.NetworkPolicyEgressRul
364418 }
365419}
366420
367- func CustomizeNetworkPolicy (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , ba common.BaseComponent ) {
421+ func GetEndpointPortByName (endpointPorts * []corev1.EndpointPort , name string ) * corev1.EndpointPort {
422+ if endpointPorts != nil {
423+ for _ , endpointPort := range * endpointPorts {
424+ if endpointPort .Name == name {
425+ return & endpointPort
426+ }
427+ }
428+ }
429+ return nil
430+ }
431+
432+ func CreateNetworkPolicyPortFromEndpointPort (endpointPort * corev1.EndpointPort ) networkingv1.NetworkPolicyPort {
433+ port := networkingv1.NetworkPolicyPort {}
434+ port .Protocol = & endpointPort .Protocol
435+ var portNumber intstr.IntOrString = intstr .FromInt ((int )(endpointPort .Port ))
436+ port .Port = & portNumber
437+ return port
438+ }
439+
440+ func CustomizeNetworkPolicy (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , getDNSEgressRule func (string , string ) (bool , networkingv1.NetworkPolicyEgressRule ), getEndpoints func (string , string ) (* corev1.Endpoints , error ), ba common.BaseComponent ) {
368441 obj := ba .(metav1.Object )
369442 networkPolicy .Labels = ba .GetLabels ()
370443 networkPolicy .Annotations = MergeMaps (networkPolicy .Annotations , ba .GetAnnotations ())
@@ -402,7 +475,8 @@ func CustomizeNetworkPolicy(networkPolicy *networkingv1.NetworkPolicy, isOpenShi
402475 if ! hasEgressPolicy {
403476 networkPolicy .Spec .PolicyTypes = append (networkPolicy .Spec .PolicyTypes , networkingv1 .PolicyTypeEgress )
404477 }
405- networkPolicy .Spec .Egress = createNetworkPolicyEgressRules (networkPolicy , isOpenShift , ba )
478+ egressBypass := ba .GetNetworkPolicy () != nil && ba .GetNetworkPolicy ().IsBypassingDenyAllEgress () // check if egress should bypass deny all policy to access the API server and DNS
479+ networkPolicy .Spec .Egress = createNetworkPolicyEgressRules (networkPolicy , isOpenShift , egressBypass , getDNSEgressRule , getEndpoints , ba )
406480 } else {
407481 // if egress is not configured, consider the network policy disabled
408482 if hasEgressPolicy {
0 commit comments