
Tengo una arquitectura de microservicio más o menos compleja, donde Apache Ignite se utiliza como base de datos/caché sin estado. El Ignite Pod
es el único Pod
en su tipo Namespace
y la arquitectura tiene que pasar una auditoría de seguridad, que no pasará si no aplico las restricciones más restrictivas NetworkPolicy
posibles para egress
el tráfico. Tiene que restringir todo el tráfico posible que no sea necesario para Ignite.
Al principio pensé:Bien, Ignite no envía tráfico a otros Pod
(no hay otros pods en ese Namespace
), por lo que esto se hará fácilmente restringiendo todo egress
el tráfico en Namespace
donde Ignite es el único Pod
....
Bueno, en realidad eso no funcionó muy bien:
cualquier egress
regla, incluso si permito el tráfico a todos los puertos mencionados en la documentación de Ignite, hará que el inicio falle con un IgniteSpiException
mensaje que diceNo se pudieron recuperar las direcciones IP de los pods Ignite, Caused by: java.net.ConnectException: Operation timed out (Connection timed out)
.
El problema parece ser elTcpDiscoveryKubernetsIpFinder
, especialmente el método getRegisteredAddresses(...)
que obviamente realiza algo de tráfico de salida dentro Namespace
para registrar las direcciones IP de los nodos Ignite. Por supuesto, el puerto de descubrimiento 47500 está permitido, pero eso no cambia la situación. La funcionalidad de Ignite con los otros Pod
s de otros Namespace
s funciona sin egress
reglas aplicadas, lo que significa (para mí) que la configuración relativa a ClusterRole
, ClusterRoleBinding
, a Service
en Namespace
y la configuración xml del propio Ignite, etc., parece ser correcta. Incluso ingress
las reglas que restringen el tráfico de otros espacios de nombres funcionan como se esperaba, permitiendo exactamente el tráfico deseado.
Estas son las políticas que apliqué:
[TRABAJANDO, bloqueando solo el tráfico no deseado]:
## Denies all Ingress traffic to all Pods in the Namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress-in-cache-ns
namespace: cache-ns
spec:
# selecting nothing here will deny all traffic between pods in the namespace
podSelector:
matchLabels: {}
# traffic routes to be considered, here: incoming exclusively
policyTypes:
- Ingress
## Allows necessary ingress traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: netpol-cache-ns
namespace: cache-ns
# defines the pod(s) that this policy is targeting
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
app: ignite
# <----incoming traffic----
ingress:
- from:
- namespaceSelector:
matchLabels:
zone: somewhere-else
podSelector:
matchExpressions:
- key: app
operator: In
values: [some-pod, another-pod] # dummy names, these Pods don't matter at all
ports:
- port: 11211 # JDBC
protocol: TCP
- port: 47100 # SPI communication
protocol: TCP
- port: 47500 # SPI discovery (CRITICAL, most likely...)
protocol: TCP
- port: 10800 # SQL
protocol: TCP
# ----outgoing traffic---->
# NONE AT ALL
Con estos dos aplicados, todo funciona bien, pero la auditoría de seguridad dirá algo como
¿Para dónde están las restricciones egress
? ¿Qué pasa si este nodo es pirateado a través de las rutas permitidas porque uno de los Pods que usa estas rutas fue pirateado antes? ¡Entonces puede llamar a un servidor C&C! Esta configuración no estará permitida, ¡reforza tu arquitectura!
[BLOQUEO del tráfico deseado/necesario]:
Generalmente niega todo el tráfico...
## Denies all traffic to all Pods in the Namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-traffic-in-cache-ns
namespace: cache-ns
spec:
# selecting nothing here will deny all traffic between pods in the namespace
podSelector:
matchLabels: {}
# traffic routes to be considered, here: incoming exclusively
policyTypes:
- Ingress
- Egress # <------ THIS IS THE DIFFERENCE TO THE WORKING ONE ABOVE
... y permitir rutas específicas después
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: netpol-cache-ns-egress
namespace: cache-ns
# defines the pod(s) that this policy is targeting
spec:
policyTypes:
- Egress
podSelector:
matchLabels:
app: ignite
----outgoing traffic---->
egress:
# [NOT SUFFICIENT]
# allow egress to this namespace at specific ports
- to:
- namespaceSelector:
matchLabels:
zone: cache-zone
ports:
- protocol: TCP
port: 10800
- protocol: TCP
port: 47100 # SPI communication
- protocol: TCP
port: 47500
# [NOT SUFFICIENT]
# allow dns resolution in general (no namespace or pod restriction)
- ports:
- protocol: TCP
port: 53
- protocol: UDP
port: 53
# [NOT SUFFICIENT]
# allow egress to the kube-system (label is present!)
- to:
- namespaceSelector:
matchLabels:
zone: kube-system
# [NOT SUFFICIENT]
# allow egress in this namespace and for the ignite pod
- to:
- namespaceSelector:
matchLabels:
zone: cache-zone
podSelector:
matchLabels:
app: ignite
# [NOT SUFFICIENT]
# allow traffic to the IP address of the ignite pod
- to:
- ipBlock:
cidr: 172.21.70.49/32 # won't work well since those addresses are dynamic
ports:
- port: 11211 # JDBC
protocol: TCP
- port: 47100 # SPI communication
protocol: TCP
- port: 47500 # SPI discovery (CRITICAL, most likely...)
protocol: TCP
- port: 49112 # JMX
protocol: TCP
- port: 10800 # SQL
protocol: TCP
- port: 8080 # REST
protocol: TCP
- port: 10900 # thin clients
protocol: TCP
La versión de Apache Ignite utilizada es 2.10.0
Ahora la pregunta para todos los lectores es:
¿Cómo puedo restringir Egress
a un mínimo absoluto el interior Namespace
para que Ignite se inicie y funcione correctamente? ¿Sería suficiente simplemente negarlo Egress
fuera del clúster?
Si necesita más yaml
datos para una suposición o sugerencia fundamentada, no dude en solicitarlos en un comentario.
Y perdón por etiquetar si parece inapropiado, no pude encontrar la etiqueta kubernetes-networkpolicy
porque está presente en stackoverflow.
ACTUALIZAR:
Ejecutar nslookup -debug kubernetes.default.svc.cluster.local
desde el interior del módulo de encendido sin que se egress
muestre ninguna política que restrinja
BusyBox v1.29.3 (2019-01-24 07:45:07 UTC) multi-call binary.
Usage: nslookup HOST [DNS_SERVER]
Query DNS about HOST
Tan pronto como NetworkPolicy
se aplica (cualquiera) que restrinja Egress
a puertos, pods y espacios de nombres específicos, el pod Ignite se niega a iniciarse y la búsqueda ya no llega kubernetes.default.svc.cluster.local
.
Egress
a DNS estaba permitido (UDP 53 a k8s-app: kube-dns) ⇒ todavía no es posible buscar IP