Configurando Zero Trust AuthN/AuthZ con Istio - BONUS - ZTN multicluster con Gloo-Mesh.
INTRO
Vamos a configurar nuestros objetos K8s para que verifiquen de forma mandatoria el origen de sus requests mediante la implementación de objetos de la API de seguridad de Istio.
Ya todo conocemos (o al menos hemos oído hablar) el concepto de Zero Trust Networks ya que no es un concepto nuevo (existe mucho antes del auge de los cloud públicos), sin embargo fue con la llegada del cloud que este tipo de políticas volvió a tomar protagonismo y mejor aún, hoy existen herramientas mucho más modernas y más acordes para encarar este tipo de desafíos en ambientes cloud native, de microservicios, etc.
La primer parte de este post (Istio Objects) la pude implementar con éxito en varios clusters K8s EKS (AWS), AKS (Azure), DOK (Digital Ocean); no es el caso de la segunda parte (Gloo-Mesh) que llegué a implementarla con un solo cliente en producción sobre un cluster AKS (Azure), básicamente porque requiere una herramienta de pago (que no es nada barata, pero que vale cada centavo), pero dejo la experiencia en este post ya que considero que es bueno conocer a los key-players en cuestiones de multi-cluster ya que es un área de muy poco desarrollo, y al mismo tiempo, claramente es un área que tiene mucha salida laboral.
Istio Demo App
Como primer paso vamos a instalar Istio con conjunto con una aplicación demo que nos ofrece la docu oficial en este enlace, sin embargo, si ya tienes Istio instalado y tienes a tu alcance alguna aplicación lista para aplicar seguridad con Istio, recomiendo que lo hagas directamente sobre dicha aplicación, en ambientes bajos obvio ;)
Si decides ir por la app demo, deberías ver la main page de BookInfo, que tiene más o menos esta facha dependiendo de la versión:
Parte I: Securizando AuthN/AuthZ con Istio Objects
Default en tu Mesh: “No confíes en nadie”
En un modelo Zero Trust, no deberíamos permitir la comunicación entre servicios (incluso dentro del mismo cluster) a menos que lo especifiquemos de manera explícita, estas configuraciones son sencillas de lograr con un objeto de la API de seguridad de Istio llamado Authorization Policy, authpol de ahora en adelante, así que como primer paso, vamos a denegar todo el tráfico para nuestra app de prueba, y posteriormente, vamos a ir habilitando por tramos, un salto a la vez, más seguro no se consigue xD.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-nothing
namespace: default
spec:
{}
Ahora que tenemos nuestro “allow-nothing” prendido, cualquier intento que haga un pod de hablar con otro va a tirar un error 4xx
Ahora vamos a crear una authpol llamada productpage-viewer para habilitar el acceso cía GET a la página de productpage, en el ejemplo falta la key “from”, lo que significa que todos los orígenes de las requests están permitidos:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "productpage-viewer"
namespace: default
spec:
selector:
matchLabels:
app: productpage
action: ALLOW
rules:
- to:
- operation:
methods: ["GET"]
Después de aplicar este manifest vamos a notar que llegamos nuevamente a la main page de Bookinfo, pero también veremos que la mainpage tiene varios errores, justamente relacionados a que no se está pudiendo comunicar con otros pods para traer esa data, vamos a hacer lo mismo con el resto del flujo aplicando las siguientes authpol:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "details-viewer"
namespace: default
spec:
selector:
matchLabels:
app: details
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
to:
- operation:
methods: ["GET"]
Review-viewer:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "reviews-viewer"
namespace: default
spec:
selector:
matchLabels:
app: reviews
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/bookinfo-productpage"]
to:
- operation:
methods: ["GET"]
Ratings-viewer:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "ratings-viewer"
namespace: default
spec:
selector:
matchLabels:
app: ratings
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/bookinfo-reviews"]
to:
- operation:
methods: ["GET"]
Si accedemos a nuestro Kiali y seguimos el data-flow mientras aplicamos los manifests, veremos mucho mejor la potencia que tienen las Istio authpol en nuestro cluster, veremos nuestro data-flow en tiempo real en color verde, y las denegaciones de requests en rojo, en otras palabras, veremos exactamente donde se corta la comunicación entre microservicios y cómo la vamos habilitando por tramos, una hermosura:
Parte II: Gloo-Mesh
El tema con Istio Objetcs:
Está todo muy lindo con las authpol, el problema es que en la vida real, casi nunca contamos con UN solo k8s cluster, por lo general son un par como mínimo, y recuerdo que pude trabajar en una compañía que tenía mas de 170 clusters AKS, entonces, las authpol que definimos en la parte I de este post, solamente tienen vida dentro del scope del istio control plane (o istiod) de un solo cluster, que hacemos si tenemos más de un cluster? y no solo con el tema de la seguridad, que pasa si queremos implementar un Canary en muchos clusters a la vez, si tenemos 170 clusters por ejemplo, no podemos estar definiendo 170 virtualServices, 170 DestinationsRules, 170… bueno, creo que se entendió el punto, este es el esquema de Istio sobre un solo cluster
ahí es donde entra este maravilloso producto de la gente de solo.io llamado Gloo-Mesh, en donde básicamente podemos llevar lo de authpol a un esquema multicluster, prendiendo algo llamado Global Access Control, mediante un objeto llamado VirtualMesh, en donde podemos concentrar la administración de más de un Istio Control Plane, simplemente pasando los meshes en forma de arrays, una locura linda:
apiVersion: networking.smh.solo.io/v1alpha2
kind: VirtualMesh
metadata:
name: virtual-mesh
namespace: service-mesh-hub
spec:
mtlsConfig:
autoRestartPods: true
shared:
rootCertificateAuthority:
generated: null
federation: {}
globalAccessPolicy: ENABLED
meshes:
- name: istiod-istio-system-cluster1
namespace: service-mesh-hub
- name: istiod-istio-system-cluster2
namespace: service-mesh-hub
Cuando levantemos este objeto, Gloo-Mesh levantará authpol en ambos clusters, o mejor dicho en TODOS los clusters que sean miembro de nuestro VirtualMesh:
Tendremos nuestro “allow-nothing” definido con un solo manifest, pero implementado N veces (siendo N la cantidad de clusters en nuestro virtualMesh), claramente quitando overhead en mantenimiento de repos.
Ahora, cómo vamos habilitando el tráfico con Gloo-Mesh?, simplemente levantamos otro objeto llamado AccessPolicy, en el cual podemos discriminar nuestras rules a nivel cluster, y dicho objeto, se va a traducir y va a crear las correspondientes authpol en los clusters que le indiquemos, por ejemplo el siguiente manifest va a crear el productpage viewer vamos el scope específico del cluster1:
apiVersion: networking.smh.solo.io/v1alpha2
kind: AccessPolicy
metadata:
namespace: service-mesh-hub
name: istio-ingressgateway
spec:
sourceSelector:
- kubeServiceAccountRefs:
serviceAccounts:
- name: istio-ingressgateway-service-account
namespace: istio-system
clusterName: cluster1
destinationSelector:
- kubeServiceMatcher:
namespaces:
- default
labels:
service: productpage
clusters:
- cluster1
Esto es solamente una pequeña introducción y la punta del iceberg de todas las posibilidades que tenemos con herramientas Open Source como Istio, y también con este tipo de productos como Gloo-Mesh, si están buscando buenas herramientas para implementar service-mesh en sus compañías,definitivamente es por acá
Fuente
Material Extra: Curso “Devops en 5 Pasos” Disponible en Udemy
Temas:
- Docker
- Kubernetes
- MultiCloud (AWS - Azure - GCP)
- IaC (Terraform, Cloud Formation, ARM Templates, Cloud Resource Manager)
- CI/CD Pipelines (GitlabCI, Azure Devops, CircleCI)
Descripción completa: Detalle y enlaces del curso