# Networking Security para Kubernetes

## Introducción

No descubrimos nada al decir que las políticas de networking son esenciales para asegurar y manejar el tráfico dentro de nuestro cluster. Nos habilitan a controlar la comunicación entre pods, mejorar la seguridad, proveer un control granular del tráfico en estos ambientes escalables como nuestros clusters de Kubernetes. La manera de mantener una infraestructura segura y eficiente.

## Ambiente

En esta entrada vamos a descubrir algunas políticas a implementar, para ello sera necesario crear un ambiente. Elegí este proyecto que tiene 2 tiers, un Backend con MySQL y un Frontend con Flask. Dejó el [proyecto](https://medium.com/@hussainwalihussain/deployment-of-two-tier-application-through-kubernetes-7dd91147a0b7), para que puedan crear el ambiente.

Vamos a ver que tenemos en el cluster.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721149298827/39ac453d-6957-4b04-b1e9-78c78088f0bc.png align="center")

Debería verse algo así.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721149415271/674d6114-db93-4d62-ab6e-8e23f3bc8b07.png align="center")

Vamos a generar las políticas necesarias para asegurar este aplicativo. La idea es que solo el Frontend atienda las consultas.

## Políticas

## 1.**Default Deny All Ingress and Egress**

Esta política es una medida de seguridad básica, donde vamos a impedir todo el tráfico de entrada y salida a los pods, actua como un firewall que bloquea todo el tráfico salvo que especifiquemos lo contrario. Es una buena practica bloquear todo el trafico e ir gradualmente añadiendo reglas que permitan las comunicaciones necesarias.  
  
Para implementar una política de negación, por defecto, debemos crear un objeto **NetworkPolicy**. En este caso aplicará sobre el namespace **default** y denegaremos el ingreso y egreso.

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
```

Perfecto, ya no podemos ingresar a nuestra aplicación.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721225361880/531fa441-e141-4a8f-a668-68e53d2c46f0.png align="center")

## 2.**Allow Frontend to 0.0.0.0**

Vamos agregar una política para que solo pueda consumirse el frontend.

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-two-tier-app
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: two-tier-app
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 0.0.0.0/0
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721225607492/7c9be2e0-e9dd-47b5-8e8d-9b2305dcfd23.png align="center")

¿Que está pasado? Ahora si podemos ingresar al frontend, pero el frontend no logra conectarse con el backend. Afinamos una nueva política, para que tengamos conexión a la Base de Datos. Vamos a crear dos políticas, una para que two-tier-app se comunique con mysql en el puerto 3306 y otra para que mysql pueda devolver el resultado a two-tier-app.

Primero veamos los labels, para trabajar mejor.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721230401506/fed37505-62c3-4ee2-b1c8-caf34a57f12c.png align="center")

## 3.**Allow Frontend to Backend**

Ahora si creamos las políticas. La primera permitimos la comunicación de two-tier-app a mysql en el puerto 3306.

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-two-tier-app-to-mysql
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: mysql
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: two-tier-app
    ports:
    - protocol: TCP
      port: 3306
```

La segunda, permitimos que mysql retorne el resultado.

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-mysql-to-two-tier-app
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: two-tier-app
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: mysql
    ports:
    - protocol: TCP
      port: 3306
```

¡Listo! Ya podemos acceder a la aplicación, que ahora se comunica con la base de datos. Sin embargo, ningún pod, excepto la aplicación, puede conectarse con el exterior.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721232425576/b0717f13-88f2-48cf-85ca-4adf712a484a.png align="center")

Vamos a hacer una prueba desde los diferentes containers. Si hacemos un curl desde el Frontend, vamos a obtener esta respuesta.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721232963313/8e54d780-937c-473a-8e14-765dd2b2a445.png align="center")

Pero si lo hacemos desde el Backend, el resultado será diferente porque solamente el label two-tier-app tiene permisos para las comunicaciones con el exterior.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721233181378/d2982eac-0ab6-49ca-bc33-956d2de6d049.png align="center")

Existen muchas clases de políticas para mejorar la seguridad, como conexiones entre namespaces, restriccion de rangos, manejar comunicaciones atraves de labels, combinaciones entre Pods y Namespaces, etc.

Espero que les sirva para dar los primeros pasos en esta clase de objetos tan necesarios.
