Skip to main content

Pregunta 13 | Restringir Acceso al Servidor de Metadatos

Usar contexto: kubectl config use-context infra-prod

Hay un servicio de metadatos disponible en http://192.168.100.21:32000 al que los Nodos pueden acceder para datos sensibles, como credenciales de nube para inicialización. Por defecto, todos los Pods en el clúster también tienen acceso a este endpoint. El equipo DevSecOps te ha pedido que restrinjas el acceso a este servidor de metadatos.

En el Namespace metadata-access:

Crea una NetworkPolicy llamada metadata-deny que prevenga el egress a 192.168.100.21 para todos los Pods pero aún permita acceso a todo lo demás

Crea una NetworkPolicy llamada metadata-allow que permita a los Pods con la etiqueta role: metadata-accessor acceder al endpoint 192.168.100.21

Hay Pods existentes en el Namespace objetivo con los que puedes probar tus políticas, pero no cambies sus etiquetas.


Respuesta:

Hubo un hack famoso en Shopify que se basó en información revelada a través de metadatos para nodos.

Verifica los Pods en el Namespace metadata-access y sus etiquetas:

➜ k -n metadata-access get pods --show-labels
NAME ... LABELS
pod1-7d67b4ff9-xrcd7 ... app=pod1,pod-template-hash=7d67b4ff9
pod2-7b6fc66944-2hc7n ... app=pod2,pod-template-hash=7b6fc66944
pod3-7dc879bd59-hkgrr ... app=pod3,role=metadata-accessor,pod-template-hash=7dc879bd59

Hay tres Pods en el Namespace y uno de ellos tiene la etiqueta role=metadata-accessor.

Verifica el acceso al servidor de metadatos desde los Pods:

➜ k exec -it -n metadata-access pod1-7d67b4ff9-xrcd7 -- curl http://192.168.100.21:32000
metadata server

➜ k exec -it -n metadata-access pod2-7b6fc66944-2hc7n -- curl http://192.168.100.21:32000
metadata server

➜ k exec -it -n metadata-access pod3-7dc879bd59-hkgrr -- curl http://192.168.100.21:32000
metadata server

Los tres pueden acceder al servidor de metadatos.

Para restringir el acceso, creamos una NetworkPolicy para denegar el acceso a la IP específica.

vim 13_metadata-deny.yaml
# 13_metadata-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: metadata-deny
namespace: metadata-access
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 192.168.100.21/32
k -f 13_metadata-deny.yaml apply

NOTA: Deberías conocer sobre las NetworkPolcies predeterminadas de denegación K8s en general.

Verifica que el acceso al servidor de metadatos ha sido bloqueado, pero otros endpoints aún son accesibles:

➜ k exec -it -n metadata-access pod1-7d67b4ff9-xrcd7 -- curl http://192.168.100.21:32000
curl: (28) Failed to connect to 192.168.100.21 port 32000: Operation timed out
command terminated with exit code 28

➜ kubectl exec -it -n metadata-access pod1-7d67b4ff9-xrcd7 -- curl -I https://kubernetes.io
HTTP/2 200
cache-control: public, max-age=0, must-revalidate
content-type: text/html; charset=UTF-8
date: Mon, 14 Sep 2020 15:39:39 GMT
etag: "b46e429397e5f1fecf48c10a533f5cd8-ssl"
strict-transport-security: max-age=31536000
age: 13
content-length: 22252
server: Netlify
x-nf-request-id: 1d94a1d1-6bac-4a98-b065-346f661f1db1-393998290

De manera similar, verifica para los otros dos Pods.

Ahora crea otra NetworkPolicy que permita el acceso al servidor de metadatos desde Pods con la etiqueta role=metadata-accessor.

vim 13_metadata-allow.yaml
# 13_metadata-allow.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: metadata-allow
namespace: metadata-access
spec:
podSelector:
matchLabels:
role: metadata-accessor
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 192.168.100.21/32
k -f 13_metadata-allow.yaml apply

Verifica que el Pod requerido tiene acceso al endpoint de metadatos y otros no:

➜ k -n metadata-access exec pod3-7dc879bd59-hkgrr -- curl http://192.168.100.21:32000
metadata server

➜ k -n metadata-access exec pod2-7b6fc66944-9ngzr -- curl http://192.168.100.21:32000
^Ccommand terminated with exit code 130

Solo funciona para el Pod que tiene la etiqueta. Con esto implementamos las restricciones de seguridad requeridas.

Si un Pod no tiene una NetworkPolicy coincidente entonces todo el tráfico está permitido desde y hacia él. Una vez que un Pod tiene una NP coincidente entonces las reglas contenidas son aditivas. Esto significa que para los Pods que tienen la etiqueta metadata-accessor las reglas se combinarán en:

# políticas fusionadas en una para pods con etiqueta metadata-accessor
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to: # primera regla
- ipBlock: # condición 1
cidr: 0.0.0.0/0
except:
- 192.168.100.21/32
- to: # segunda regla
- ipBlock: # condición 1
cidr: 192.168.100.21/32

Podemos ver que la NP fusionada contiene dos reglas separadas con una condición cada una. Podríamos leerlo como:

Permitir tráfico saliente si: (destino es 0.0.0.0/0 pero no 192.168.100.21/32) O (destino es 192.168.100.21/32)

Por lo tanto, permite a los Pods con etiqueta metadata-accessor acceder a todo.