@@ -340,19 +340,73 @@ func customizeProbeDefaults(config *corev1.Probe, defaultProbe *corev1.Probe) *c
340340 return probe
341341}
342342
343+ func createEgressBypass (ba common.BaseComponent , isOpenShift bool , getDNSEgressRule func (string , string ) (bool , networkingv1.NetworkPolicyEgressRule ), getEndpoints func (string , string ) (* corev1.Endpoints , error )) (bool , []networkingv1.NetworkPolicyEgressRule ) {
344+ egressRules := []networkingv1.NetworkPolicyEgressRule {}
345+
346+ var dnsRule networkingv1.NetworkPolicyEgressRule
347+ var usingPermissiveRule bool
348+ // If allowed, add an Egress rule to access the OpenShift DNS or K8s CoreDNS. Otherwise, use a permissive cluster-wide Egress rule.
349+ if isOpenShift {
350+ usingPermissiveRule , dnsRule = getDNSEgressRule ("dns-default" , "openshift-dns" )
351+ } else {
352+ usingPermissiveRule , dnsRule = getDNSEgressRule ("kube-dns" , "kube-system" )
353+ }
354+ egressRules = append (egressRules , dnsRule )
355+
356+ // If the DNS rule is a specific Egress rule also check if another Egress rule can be created for the API server.
357+ // Otherwise, fallback to a permissive cluster-wide Egress rule.
358+ if ! usingPermissiveRule {
359+ if apiServerEndpoints , err := getEndpoints ("kubernetes" , "default" ); err == nil {
360+ rule := networkingv1.NetworkPolicyEgressRule {}
361+ // Define the port
362+ port := networkingv1.NetworkPolicyPort {}
363+ port .Protocol = & apiServerEndpoints .Subsets [0 ].Ports [0 ].Protocol
364+ var portNumber intstr.IntOrString = intstr .FromInt ((int )(apiServerEndpoints .Subsets [0 ].Ports [0 ].Port ))
365+ port .Port = & portNumber
366+ rule .Ports = append (rule .Ports , port )
367+
368+ // Add the endpoint address as ipBlock entries
369+ for _ , endpoint := range apiServerEndpoints .Subsets {
370+ for _ , address := range endpoint .Addresses {
371+ peer := networkingv1.NetworkPolicyPeer {}
372+ ipBlock := networkingv1.IPBlock {}
373+ ipBlock .CIDR = address .IP + "/32"
374+
375+ peer .IPBlock = & ipBlock
376+ rule .To = append (rule .To , peer )
377+ }
378+ }
379+ egressRules = append (egressRules , rule )
380+ } else {
381+ // The operator couldn't create a rule for the K8s API server so add a permissive Egress rule
382+ rule := networkingv1.NetworkPolicyEgressRule {}
383+ egressRules = append (egressRules , rule )
384+ }
385+ }
386+ return usingPermissiveRule , egressRules
387+ }
388+
343389// createNetworkPolicyEgressRules returns the network policy rules for outgoing traffic to other Pod(s)
344- func createNetworkPolicyEgressRules (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , ba common.BaseComponent ) []networkingv1.NetworkPolicyEgressRule {
390+ 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 {
345391 config := ba .GetNetworkPolicy ()
392+ egressRules := []networkingv1.NetworkPolicyEgressRule {}
393+ if isBypassingDenyAllEgress {
394+ usingPermissiveRule , bypassRules := createEgressBypass (ba , isOpenShift , getDNSEgressRule , getEndpoints )
395+ egressRules = append (egressRules , bypassRules ... )
396+ if usingPermissiveRule {
397+ return egressRules // exit early because permissive egress is set
398+ }
399+ }
400+ // configure the main application egress rule
346401 var rule networkingv1.NetworkPolicyEgressRule
347-
348402 if config == nil || ((config .GetToNamespaceLabels () != nil && len (config .GetToNamespaceLabels ()) == 0 ) &&
349403 (config .GetToLabels () != nil && len (config .GetToLabels ()) == 0 )) {
350404 rule = createAllowAllNetworkPolicyEgressRule ()
351405 } else {
352406 rule = createNetworkPolicyEgressRule (ba .GetApplicationName (), networkPolicy .Namespace , config )
353407 }
354-
355- return []networkingv1. NetworkPolicyEgressRule { rule }
408+ egressRules = append ( egressRules , rule )
409+ return egressRules
356410}
357411
358412func createNetworkPolicyEgressRule (appName string , namespace string , config common.BaseComponentNetworkPolicy ) networkingv1.NetworkPolicyEgressRule {
@@ -374,7 +428,26 @@ func createAllowAllNetworkPolicyEgressRule() networkingv1.NetworkPolicyEgressRul
374428 }
375429}
376430
377- func CustomizeNetworkPolicy (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , ba common.BaseComponent ) {
431+ func GetEndpointPortByName (endpointPorts * []corev1.EndpointPort , name string ) * corev1.EndpointPort {
432+ if endpointPorts != nil {
433+ for _ , endpointPort := range * endpointPorts {
434+ if endpointPort .Name == name {
435+ return & endpointPort
436+ }
437+ }
438+ }
439+ return nil
440+ }
441+
442+ func CreateNetworkPolicyPortFromEndpointPort (endpointPort * corev1.EndpointPort ) networkingv1.NetworkPolicyPort {
443+ port := networkingv1.NetworkPolicyPort {}
444+ port .Protocol = & endpointPort .Protocol
445+ var portNumber intstr.IntOrString = intstr .FromInt ((int )(endpointPort .Port ))
446+ port .Port = & portNumber
447+ return port
448+ }
449+
450+ func CustomizeNetworkPolicy (networkPolicy * networkingv1.NetworkPolicy , isOpenShift bool , getDNSEgressRule func (string , string ) (bool , networkingv1.NetworkPolicyEgressRule ), getEndpoints func (string , string ) (* corev1.Endpoints , error ), ba common.BaseComponent ) {
378451 obj := ba .(metav1.Object )
379452 networkPolicy .Labels = ba .GetLabels ()
380453 networkPolicy .Annotations = MergeMaps (networkPolicy .Annotations , ba .GetAnnotations ())
@@ -412,7 +485,8 @@ func CustomizeNetworkPolicy(networkPolicy *networkingv1.NetworkPolicy, isOpenShi
412485 if ! hasEgressPolicy {
413486 networkPolicy .Spec .PolicyTypes = append (networkPolicy .Spec .PolicyTypes , networkingv1 .PolicyTypeEgress )
414487 }
415- networkPolicy .Spec .Egress = createNetworkPolicyEgressRules (networkPolicy , isOpenShift , ba )
488+ egressBypass := ba .GetNetworkPolicy () != nil && ba .GetNetworkPolicy ().IsBypassingDenyAllEgress () // check if egress should bypass deny all policy to access the API server and DNS
489+ networkPolicy .Spec .Egress = createNetworkPolicyEgressRules (networkPolicy , isOpenShift , egressBypass , getDNSEgressRule , getEndpoints , ba )
416490 } else {
417491 // if egress is not configured, consider the network policy disabled
418492 if hasEgressPolicy {
0 commit comments