Networking Security para Kubernetes
Las políticas juegan un papel fundamental para definir como los pods interactúan entre ellos o con redes externas.
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, para que puedan crear el ambiente.
Vamos a ver que tenemos en el cluster.
Debería verse algo así.
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.
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.
2.Allow Frontend to 0.0.0.0
Vamos agregar una política para que solo pueda consumirse el frontend.
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
¿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.
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.
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.
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.
Vamos a hacer una prueba desde los diferentes containers. Si hacemos un curl desde el Frontend, vamos a obtener esta respuesta.
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.
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.