Network Policy Configuration

If a Network Policy object is defined in a namespace, it acts as an explicit allow list and all other traffic is denied. If there is no Network Policy object, all traffic is allowed in to that namespaces.

In order to control traffic flows in between namespaces and pods, selectors inside the Network Policy objects are used to explicitly allow traffic.

Multiple networkpolicy objects can be created in the same namespace to make it clear which rules are allowing traffic through.

Allow Pod to Pod - Same Namespace

To simply allow traffic between pods in the same namespace, this would be the yaml to apply:


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-same-namespace
spec:
  ingress:
  - from:
    - podSelector: {}
  podSelector: {}
  policyTypes:
  - Ingress

The key part of this is spec.ingress[0].from[0].podSelector: {} which allows traffic between all the pods matched in that namespaces.

This configuration will disable traffic from the openshift Ingress pods.

Allow Openshift Ingress

An example to allow Openshift Ingress routes to any pod in the namespace


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-openshift-ingress
spec:
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          network.openshift.io/policy-group: ingress
  podSelector: {}
  policyTypes:
  - Ingress

This will not allow traffic between pods inside the namespace, but will allow Openshift routes to communicate with their backing pod inside the namespace.

Allow Pod-Pod and Openshift Ingress

The spec.ingress.from is an array of allowed rules to be applied in the network policy, so can be chained together. For example, this will allow both the Openshift Ingress routes and pod - pod traffic, but will not allow other namespaces access into these pods.


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress-and-namespace
spec:
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          network.openshift.io/policy-group: ingress
    - podSelector: {}
  podSelector: {}
  policyTypes:
  - Ingress

Advanced Examples

For these to work, either the pod or the namespaces or both require labels.

To label a namespace:


# oc label namespace <namespace> name=<namespace>
namespace/project1 labeled

To label a pod: (Note: this will only persist for the lifetime of the pod. It will need to be defined to persist)


# oc label pod pod2-1-ksmjx name=pod2
pod/pod2-1-ksmjx labeled

All pods in project A to a specific service/pod to project B

In this example, we want all pods in project1 to be able to access pod2 in project2

In this example:

  • project2 has an existing network policy that only allows traffic between pods in that namespace (see Allow Pod to Pod).
  • project1 has the label ingressname=project1
  • pod2 in project2 has the label name=pod2
  • Namespace label
    
    # oc get namespaces -l name=project1
    NAME       STATUS   AGE
    project1   Active   140m
    
  • Pod label
    
    # oc -n project2 get pods -l ingressname=pod2
    NAME           READY   STATUS    RESTARTS   AGE
    pod2-4-6msv5   1/1     Running   0          15m
    

This will allow traffic in from namespace project1 to just pod2:


kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-namespace-to-pod
spec:
  podSelector:
    matchLabels:
      ingressname: pod2
  ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            name: project1

Once this is created


# oc -n project2 create -f allow-namespace-to-pod.yaml
networkpolicy.networking.k8s.io/allow-namespace-to-pod created 

Traffic is now able to reach pod2 from pods inside project1.

Specific pod in project A to a specific service/pod to project B

Similarly to allowing all traffic in from a namespace label, here we can allow traffic in from a pod label that exists in the cluster.

In this example:

  • project2 has an existing network policy that only allows traffic between pods in that namespace (see Allow Pod to Pod).
  • pod3 in project2 has the label: ingressname=pod3
  • project1 has the label name=project1
  • pod2 in project1 has the label: name=project1-pod2
  • Pod label

    
    # oc -n project2 get pods -l ingressname=pod3
    NAME           READY   STATUS    RESTARTS   AGE
    pod3-1-jxpd8   1/1     Running   0          14m
    

  • Namespace label

    
    # oc get pods --all-namespaces -l name=project1-pod2
    NAMESPACE   NAME           READY   STATUS    RESTARTS   AGE
    project1    pod2-1-ksmjx   1/1     Running   0          126m
    

This will now allow access from pod2 in project1 to pod3 in project2


kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-pod-to-pod-x-namespace
spec:
  podSelector:
    matchLabels:
      ingressname: pod3
  ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            name: project1
        podSelector:
          matchLabels:
            name: project1-pod2

Update existing Projects

In order to update existing projects, all that is required is to add a NetworkPolicy object to the namespace. Should this interfere with the operation of the pods in that namespace, removing the object will restore the previous allow all state.


# oc -n <target namespace> create -f <network-policy.yaml file>
networkpolicy.networking.k8s.io/allow-from-openshift-ingress created

And to remove the network policy in case of issues;


# oc -n <target namespace> delete networkpolicy <policy name>
networkpolicy.networking.k8s.io "allow-from-openshift-ingress" deleted

Update Default Project Template

To add a default Network Policy to every new project that is created, a new default project template will need to be defined.

First, generate a project template yaml:


# oc adm create-bootstrap-project-template -o yaml > template.yaml

Then add the desired default NetworkPolicy to the template. In this example it will allow all pods in the same namespace to communicate and any routes access to the pods.


# This section is added to objects
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: default-policy
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            network.openshift.io/policy-group: ingress
      - podSelector: {}
    podSelector: {}
    policyTypes:
    - Ingress

Then create this template in the openshift-config namespace


# oc create -f template.yaml -n openshift-config
template.template.openshift.io/project-request created

Once the template is created, the project resource will need to be updated to use the new template.

First edit the project.config.openshift.io/cluster resource


# oc edit project.config.openshift.io/cluster

Then add the project template to spec


spec:
  projectRequestTemplate:
    name: project-request

Now new projects will be created with a default NetworkPolicy


# oc new-project project4
# oc -n project4 get networkpolicy
NAME             POD-SELECTOR   AGE
default-policy   <none>         14s