Skip to main content

Network Security Policies

Para esta sesión podemos revisar el material del CKA. Solo voy a añadir las diferencias de contenido.

  • Son las reglas de cortafuegos en Kubernetes.
  • Implementadas por el CNI, no todos los Network Plugins las soportan.
  • Nivel de namespace.
  • Restringe el ingress y el egress para un grupo de pods basándose en ciertas condiciones.
  • Network Policies.

En este primer escenario estamos aplicando una regla de salida que está denegando todo, a menos que pase por una regla. Como no tenemos reglas, todo está denegado.

alt text

Aquí ya tenemos reglas de salida.

alt text

Podemos crear varias network policies para los mismos pods. Prácticamente es un merge.

  • Si un pod tiene más de una NP
    • Entonces tendremos la unión de todas las NP aplicadas a él.
    • El orden no importa, el resultado es siempre el mismo.

Sabiendo esto podemos crear una NP para denegar todo en cada namespace y solo ir permitiendo lo que sea necesario.

Vamos a ejecutar dos pods en el namespace default y vamos a comprobar si pueden verse entre sí.

root@cks-master:~# kubectl get pods
No resources found in default namespace.

root@cks-master:~# k run frontend --image=nginx
pod/frontend created

root@cks-master:~# k run backend --image=nginx
pod/backend created

root@cks-master:~# k expose pod frontend --port 80
service/frontend exposed

root@cks-master:~# k expose pod backend --port 80
service/backend exposed

root@cks-master:~# k get pod,svc
NAME READY STATUS RESTARTS AGE
pod/backend 1/1 Running 0 46s
pod/frontend 1/1 Running 0 59s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/backend ClusterIP 10.111.182.74 <none> 80/TCP 20s
service/frontend ClusterIP 10.104.14.250 <none> 80/TCP 27s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44h

# Ejecutando un curl dentro del frontend hacia el backend

root@cks-master:~# k exec frontend -- curl backend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 73652 0 <!DOCTYPE html>-- --:--:-- 0
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
--:--:-- --:--:-- --:--:-- 76875

root@cks-master:~# k exec backend -- curl frontend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 221k 0 --:--:-- --:--:-- --:--:-- 300k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Podemos observar que existe la comunicación. Vamos a crear una NP por defecto y solo permitir lo necesario.

Crea un archivo y aplícalo en el clúster.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
root@cks-master:~# mkdir default
root@cks-master:~# cd default/
root@cks-master:~/default# vi np-default-deny.yaml
root@cks-master:~/default# kubectl apply -f np-default-deny.yaml
networkpolicy.networking.k8s.io/default-deny created

root@cks-master:~/default# k get networkpolicies
NAME POD-SELECTOR AGE
default-deny <none> 48s
root@cks-master:~/default# k describe networkpolicies default-deny
Name: default-deny
Namespace: default
Created on: 2024-08-17 17:33:21 +0000 UTC
Labels: <none>
Annotations: <none>
Spec:
PodSelector: <none> (Allowing the specific traffic to all pods in this namespace)
Allowing ingress traffic:
<none> (Selected pods are isolated for ingress connectivity)
Allowing egress traffic:
<none> (Selected pods are isolated for egress connectivity)
Policy Types: Ingress, Egress

# Si intentamos la comunicación de nuevo vemos que ya no conseguimos la página de nginx.

root@cks-master:~/default# k exec frontend -- curl backend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:14 --:--:--
root@cks-master:~/default#

Vamos a permitir que el pod frontend salga hacia el backend.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend
namespace: default
spec:
podSelector:
matchLabels:
run: frontend # Cuando ejecutamos el comando run tenemos esta label por defecto
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
run: backend

Vamos a crear y aplicar esta policy.

root@cks-master:~/default# vim np-frontend.yaml
root@cks-master:~/default# kubectl apply -f np-frontend.yaml
networkpolicy.networking.k8s.io/frontend created
root@cks-master:~/default# k exec frontend -- curl backend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0

Aún no conseguimos la conexión porque el pod backend está denegando todo, vamos entonces a liberar su entrada.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend
namespace: default
spec:
podSelector:
matchLabels:
run: backend # Cuando ejecutamos el comando run tenemos esta label por defecto
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: frontend

Vamos a liberar la entrada para los pods del frontend en el backend y probar.

root@cks-master:~/default# vim np-backend.yaml

root@cks-master:~/default# kubectl apply -f np-backend.yaml
networkpolicy.networking.k8s.io/backend created

# Todavía no lo conseguimos
root@cks-master:~/default# k exec frontend -- curl backend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:--

root@cks-master:~/default# k get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
backend 1/1 Running 0 26m 192.168.1.3 cks-worker <none> <none>
frontend 1/1 Running 0 26m 192.168.1.2 cks-worker <none> <none>

# Intentando directamente por IP lo conseguimos
root@cks-master:~/default# k exec frontend -- curl 192.168.1.3
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
100 615 100 615 0 0 399k 0 --:--:-- --:--:-- --:--:-- 600k

Lo que está sucediendo es que no conseguimos resolver los nombres porque no hay acceso al core-dns. Necesitamos liberar esto en todos los pods del namespace. Para que esto sea fácil podemos aplicar esta regla en todos los pods de una sola vez. Podemos alterar nuestro default-deny o crear otra NP. Vamos a extender el default-deny y permitir solo el egress para el puerto 53.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
egress:
- to:
ports:
- port: 53
protocol: TCP
- port : 53
protocol: UDP
root@cks-master:~/default# vim np-default-deny.yaml

root@cks-master:~/default# k apply -f np-default-deny.yaml
networkpolicy.networking.k8s.io/default-deny configured

# Funcionando
root@cks-master:~/default# k exec frontend -- curl backend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 268k 0 --:--:-- --:--:-- --:--:-- 300k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

# Y solo para constatar, no permitimos que el backend se comunique con el frontend
# Tampoco permitimos entradas en el frontend. Solo permitimos una dirección frontend > backend.

root@cks-master:~/default# k exec backend -- curl frontend
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0^C
root@cks-master:~/default# k exec backend -- curl 192.168.1.2
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0^C
root@cks-master:~/default#