<p>I am trying to write a network policy on Kubernetes that works under AWS EKS. What I want to achieve is to allow traffic to pod/pods from the same Namespace and allow external traffic that is forwarded from AWS ALB Ingress.</p>

<p>AWS ALB Ingress is created under the same NameSpace so I was thinking that only using <a href="https://github.com/ahmetb/kubernetes-network-policy-recipes/blob/master/04-deny-traffic-from-other-namespaces.md" rel="nofollow noreferrer">DENY all traffic from other namespaces</a> would suffice but when I use that traffic from ALB Ingress Load Balancer (whose internal IP addresses are at at the same nameSpace with the pod/pods) are not allowed. Then if I add <a href="https://github.com/ahmetb/kubernetes-network-policy-recipes/blob/master/08-allow-external-traffic.md" rel="nofollow noreferrer">ALLOW traffic from external clients</a> it allows to Ingress but ALSO allows other namespaces too.</p>

<p>So my example is like: (this does not work as expected)</p>

<pre><code>---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-from-other-namespaces
  namespace: os
spec:
  podSelector:
    matchLabels:
  ingress:
  - from:
    - podSelector: {}

---

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-external
  namespace: os
spec:
  podSelector:
    matchLabels:
      app: nginx
      tier: prod
      customer: os
  ingress:
  - ports:
    - port: 80
    from: []

</code></pre>

<p>When using first policy ALB Ingress is blocked, with adding second one other namespaces are also allowed too which i dont want. I can allow only internal IP address of AWS ALB Ingress but it can change over time and it is created dynamically.</p>

Omer Sen
<p>The semantics of the built-in Kubernetes NetworkPolicies are kind of fiddly. There are no deny rules, only allow rules.</p>
<p>The way they work is if no network policies apply to a pod, then all traffic is allowed. Once there is a network policy that applies to a pod, then all traffic <em>not allowed</em> by that policy is blocked.</p>
<p>In other words, you can't say something like &quot;deny this traffic, allow all the rest&quot;. You have to effectively say, &quot;allow all the rest&quot;.</p>
<p><a href="https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html#:%7E:text=The%20AWS%20Load%20Balancer%20Controller%20supports%20the%20following%20traffic%20modes%3A" rel="nofollow noreferrer">The documentation for the AWS ALB Ingress controller states that traffic can either be sent to a NodePort for your service, or directly to pods</a>. This means that the traffic originates from an AWS IP address outside the cluster.</p>
<p>For traffic that has a source that isn't well-defined, such as traffic from AWS ALB, this can be difficult - you don't know what the source IP address will be.</p>
<p>If you are trying to allow traffic from the Internet using the ALB, then it means anyone that can reach the ALB will be able to reach your pods. In that case, there's effectively no meaning to blocking traffic within the cluster, as the pods will be able to connect to the ALB, even if they can't connect directly.</p>
<p>My suggestion then is to just create a network policy that allows all traffic to the pods the Ingress covers, but have that policy as specific as possible - for example, if the Ingress accesses a specific port, then have the network policy only allow that port. This way you can minimize the attack surface within the cluster only to that which is Internet-accessible.</p>
<p>Any other traffic to these pods will need to be explicitly allowed.</p>
<p>For example:</p>
<pre><code>---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-external
spec:
  podSelector:
    matchLabels:
      app: &lt;your-app&gt; # app-label
  ingress:
    - from: []
      ports:
        - port: 1234 # the port which should be Internet-accessible
</code></pre>
<p>This is actually a problem we faced when implementing the Network Policy plugin for the Otterize Intents operator - the operator lets you declare which pods you want to connect to within the cluster and block all the rest by automatically creating network policies and labeling pods, but we had to do that without inadvertently blocking external traffic once the first network policy had been created.</p>
<p>We settled on automatically detecting whether a <code>Service</code> resource of type <code>LoadBalancer</code> or <code>NodePort</code> exists, or an <code>Ingress</code> resource, and creating a network policy that allows all traffic to those ports, as in the example above. A potential improvement for that is to support specific Ingress controllers that have in-cluster pods (so, not AWS ALB, but could be nginx ingress controller, for example), and only allowing traffic from the specific ingress pods.</p>
<p>Have a look here: <a href="https://github.com/otterize/intents-operator" rel="nofollow noreferrer">https://github.com/otterize/intents-operator</a>
And the documentation page explaining this: <a href="https://docs.otterize.com/components/intents-operator/#network-policies" rel="nofollow noreferrer">https://docs.otterize.com/components/intents-operator/#network-policies</a></p>
<p>If you wanna use this and add support for a specific Ingress controller you're using, hop onto to the Slack or open an issue and we can work on it together.</p>
