Volver a los microservicios con Istio. Parte 3



Nota perev. : La primera parte de esta serie se dedicó a presentar las capacidades de Istio y demostrarlas en acción, la segunda al enrutamiento finamente ajustado y la gestión del tráfico de red. Ahora hablaremos de seguridad: para demostrar las funciones básicas asociadas con él, el autor utiliza el servicio de identidad Auth0, pero otros proveedores se pueden configurar por analogía.

Establecimos un clúster de Kubernetes en el que se implementaron Istio y el ejemplo de la aplicación de microservicio de Análisis de sentimientos: así se demostraron las capacidades de Istio.

Al usar Istio, pudimos mantener los servicios de tamaño pequeño, ya que no necesitan implementar "capas" como reintentos, retiros, tiempos de espera, interruptores de circuito, rastreo, monitoreo . Además, utilizamos técnicas avanzadas de prueba e implementación: pruebas A / B, duplicación y despliegues canarios.



En el nuevo material, trataremos las capas finales en el camino hacia el valor comercial: autenticación y autorización, ¡y en Istio esto es un verdadero placer!

Autenticación y autorización en Istio


Nunca hubiera creído que me inspiraría la autenticación y la autorización. ¿Qué tecnología puede ofrecer Istio para hacer que estos temas sean emocionantes y aún más para inspirarte?

La respuesta es simple: Istio transfiere la responsabilidad de estas funciones de sus servicios a los servidores proxy de Envoy. Cuando las solicitudes llegan a los servicios, ya están autenticadas y autorizadas, por lo que solo tiene que escribir un código útil para las empresas.

Suena bien? ¡Miremos adentro!

Autenticación con Auth0


Utilizaremos Auth0 como servidor para la gestión de identidad y acceso, que tiene una versión de prueba, que es intuitiva de usar y me gusta. Sin embargo, los mismos principios se pueden aplicar a cualquier otra implementación de OpenID Connect : KeyCloak, IdentityServer y muchos otros.

Primero, vaya al portal Auth0 con su cuenta, cree un inquilino (inquilino - "inquilino", unidad de aislamiento lógico, para más detalles vea la documentación - Transl. Aprox.) Y vaya a Aplicaciones> Aplicación predeterminada , eligiendo Dominio , como se muestra en la captura de pantalla siguiente :



Especifique este dominio en el resource-manifests/istio/security/auth-policy.yaml ( fuente ):

 apiVersion: authentication.istio.io/v1alpha1 kind: Policy metadata: name: auth-policy spec: targets: - name: sa-web-app - name: sa-feedback origins: - jwt: issuer: "https://{YOUR_DOMAIN}/" jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json" principalBinding: USE_ORIGIN 

Al tener dicho recurso, Pilot (uno de los tres componentes básicos de Control Plane en Istio - aprox. Transl.) Configura los Enviados para autenticar las solicitudes antes de redirigirlas a los servicios: sa-web-app y sa-feedback . Al mismo tiempo, la configuración no se aplica a los Enviados del sa-frontend , lo que nos permite dejar la interfaz sin autenticar. Para aplicar una política, ejecute el comando:

 $ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml policy.authentication.istio.io “auth-policy” created 

Regrese a la página y haga una solicitud; verá que termina en 401 Estado no autorizado . Ahora redirigimos a los usuarios front-end a la autenticación con Auth0.

Solicitar autenticación con Auth0


Para autenticar las solicitudes de los usuarios finales, debe crear una API en Auth0 que represente los servicios autenticados (revisiones, detalles y calificaciones). Para crear una API, vaya a Auth0 Portal> API> Crear API y complete el formulario:



La información importante aquí es Identificador , que usaremos más adelante en el script. Escribámoslo así:

  • Público : {YOUR_AUDIENCE}

Los detalles restantes que necesitamos se encuentran en el Portal Auth0 en la sección Aplicaciones : seleccione Aplicación de prueba (se crea automáticamente con la API).

Aquí escribimos:

  • Dominio : {YOUR_DOMAIN}
  • ID del cliente : {YOUR_CLIENT_ID}

Desplácese en la aplicación de prueba hasta el cuadro de texto URL de devolución de llamada permitida (URL permitidas para la devolución de llamada), en el que indicamos la URL a la que debe enviarse la llamada después de que se complete la autenticación. En nuestro caso, es:

 http://{EXTERNAL_IP}/callback 

Y para las URL de cierre de sesión permitidas ( URL permitidas para cerrar sesión), agregue:

 http://{EXTERNAL_IP}/logout 

Pasemos a la interfaz.

Actualización Frontend


Cambie a la rama [istio-mastery] repositorio [istio-mastery] . En este hilo, el código front-end se cambia para redirigir a los usuarios a Auth0 para la autenticación y usar el token JWT en las solicitudes de otros servicios. Este último se implementa de la siguiente manera ( App.js ):

 analyzeSentence() { fetch('/sentiment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token }, body: JSON.stringify({ sentence: this.textField.getValue() }) }) .then(response => response.json()) .then(data => this.setState(data)); } 

Para convertir la interfaz para usar los datos del inquilino en Auth0, abra sa-frontend/src/services/Auth.js y reemplace los valores que escribimos anteriormente ( Auth.js ) en ella:

 const Config = { clientID: '{YOUR_CLIENT_ID}', domain:'{YOUR_DOMAIN}', audience: '{YOUR_AUDIENCE}', ingressIP: '{EXTERNAL_IP}' //      } 

La aplicación está lista. Indique su ID de Docker en los siguientes comandos cuando cree y despliegue los cambios realizados:

 $ docker build -f sa-frontend/Dockerfile \ -t $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 \ sa-frontend $ docker push $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 $ kubectl set image deployment/sa-frontend \ sa-frontend=$DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 

Prueba la aplicación! Será redirigido a Auth0, donde debe iniciar sesión (o registrarse), después de lo cual será enviado de regreso a la página desde la cual se realizarán las solicitudes ya autenticadas. Si prueba los comandos curl mencionados en las primeras partes del artículo, recibirá un Código de estado 401 , que indica que la solicitud no está autorizada.

Pasemos al siguiente paso: autorizar solicitudes.

Autorización con Auth0


La autenticación nos permite comprender quién es el usuario, pero para saber a qué tiene acceso, se requiere autorización. Istio ofrece herramientas para esto también.

Como ejemplo, crearemos dos grupos de usuarios (ver el diagrama a continuación):

  • Usuarios (usuarios) : con acceso solo a los servicios SA-WebApp y SA-Frontend;
  • Moderadores : con acceso a los tres servicios.


Concepto de autorización

Para crear estos grupos, utilizaremos la extensión de Autorización Auth0 y Istio para proporcionarles diferentes niveles de acceso.

Instalación y configuración de Autorización Auth0


En el portal Auth0, vaya a Extensiones e instale la Autorización Auth0 . Después de la instalación, vaya a la Extensión de autorización y allí, a la configuración del inquilino haciendo clic en la esquina superior derecha y seleccionando la opción de menú adecuada (Configuración) . Active Grupos y haga clic en el botón Publicar regla .



Creación grupal


En la Extensión de autorización, vaya a Grupos y cree un grupo de Moderadores . Como consideraremos a todos los usuarios autenticados como ordinarios, no es necesario crear un grupo adicional para ellos.

Seleccione el grupo Moderadores , haga clic en Agregar miembros , agregue su cuenta principal. Deje a algunos usuarios sin ningún grupo para asegurarse de que se les niegue el acceso. (Los nuevos usuarios se pueden crear manualmente a través de Auth0 Portal> Usuarios> Crear usuario ).

Agregar reclamo grupal al token de acceso


Los usuarios se agregan a los grupos, pero esta información debe reflejarse en tokens de acceso. Para cumplir con OpenID Connect y al mismo tiempo devolver los grupos que necesitamos, el token deberá agregar su reclamo personalizado . Se implementa a través de las reglas de Auth0.

Para crear una regla, vaya al portal de reglas Auth0, haga clic en Crear regla y seleccione una regla vacía de las plantillas.



Copie el código a continuación y guárdelo como la nueva regla Agregar reclamo de grupo ( namespacedGroup.js ):

 function (user, context, callback) { context.accessToken['https://sa.io/group'] = user.groups[0]; return callback(null, user, context); } 

Nota : este código toma el primer grupo de usuarios definido en la Extensión de autorización y lo agrega al token de acceso como un reclamo personalizado (bajo su espacio de nombres, como lo requiere Auth0).

Regrese a la página Reglas y verifique que tiene dos reglas escritas en el siguiente orden:

  • extensión-autorización-auth0
  • Agregar reclamo grupal

El orden es importante porque el campo de grupo recibe asincrónicamente la regla de extensión de autorización auth0 y luego se agrega como un reclamo por la segunda regla. El resultado es un token de acceso:

 { "https://sa.io/group": "Moderators", "iss": "https://sentiment-analysis.eu.auth0.com/", "sub": "google-oauth2|196405271625531691872" // [  ] } 

Ahora debe configurar el proxy Envoy para verificar el acceso del usuario, para lo cual el grupo será retirado del reclamo ( https://sa.io/group ) en el token de acceso devuelto. Este es el tema para la siguiente sección del artículo.

Configuración de autorización de Istio


Para que la autorización funcione, debe habilitar RBAC para Istio. Para hacer esto, use la siguiente configuración:

 apiVersion: "rbac.istio.io/v1alpha1" kind: RbacConfig metadata: name: default spec: mode: 'ON_WITH_INCLUSION' # 1 inclusion: services: # 2 - "sa-frontend.default.svc.cluster.local" - "sa-web-app.default.svc.cluster.local" - "sa-feedback.default.svc.cluster.local" 

Explicaciones:
  • 1: habilite RBAC solo para los servicios y espacios de nombres enumerados en el campo Inclusion ;
  • 2 - enumere la lista de nuestros servicios.


Aplicamos la configuración con este comando:

 $ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml rbacconfig.rbac.istio.io/default created 

Ahora todos los servicios requieren control de acceso basado en roles. En otras palabras, se deniega el acceso a todos los servicios y dará como resultado una respuesta RBAC: access denied . Ahora permita el acceso a usuarios autorizados.

Configuración de acceso para usuarios habituales.


Todos los usuarios deben tener acceso a los servicios SA-Frontend y SA-WebApp. Implementado usando los siguientes recursos de Istio:

  • ServiceRole : define los derechos que tiene el usuario;
  • ServiceRoleBinding : determina a quién pertenece este ServiceRole.

Para usuarios comunes, permita el acceso a ciertos servicios ( servicerole.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRole metadata: name: regular-user namespace: default spec: rules: - services: - "sa-frontend.default.svc.cluster.local" - "sa-web-app.default.svc.cluster.local" paths: ["*"] methods: ["*"] 

Y a través regular-user-binding aplique un ServiceRole a todos los visitantes de la página ( regular-user-service-role-binding.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: regular-user-binding namespace: default spec: subjects: - user: "*" roleRef: kind: ServiceRole name: "regular-user" 

¿Significa "todos los usuarios" que los usuarios no autenticados tendrán acceso a SA WebApp? No, la política verificará la validez del token JWT.

Aplicar configuración:

 $ kubectl apply -f resource-manifests/istio/security/user-role.yaml servicerole.rbac.istio.io/regular-user created servicerolebinding.rbac.istio.io/regular-user-binding created 

Configuración de acceso para moderadores


Para los moderadores, queremos habilitar el acceso a todos los servicios ( mod-service-role.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRole metadata: name: mod-user namespace: default spec: rules: - services: ["*"] paths: ["*"] methods: ["*"] 

Pero queremos tales derechos solo para aquellos usuarios cuyo token de acceso tiene un reclamo https://sa.io/group con el valor Moderators ( mod-service-role-binding.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: mod-user-binding namespace: default spec: subjects: - properties: request.auth.claims[https://sa.io/group]: "Moderators" roleRef: kind: ServiceRole name: "mod-user" 

Aplicar configuración:

 $ kubectl apply -f resource-manifests/istio/security/mod-role.yaml servicerole.rbac.istio.io/mod-user created servicerolebinding.rbac.istio.io/mod-user-binding created 

Debido al almacenamiento en caché de los enviados, las reglas de autorización pueden tardar un par de minutos en surtir efecto. Después de eso, puede asegurarse de que los usuarios y moderadores tengan diferentes niveles de acceso.

Conclusión sobre esta parte


Bueno, en serio: ¿alguna vez has visto un enfoque de autenticación y autorización más simple, sin esfuerzo, escalable y seguro?

Solo se necesitaron tres recursos Istio (RbacConfig, ServiceRole y ServiceRoleBinding) para lograr un control más preciso sobre la autenticación y la autorización del acceso del usuario final a los servicios.

Además, nos ocupamos de estos problemas de nuestros servicios enviados, logrando:

  • Reducir la cantidad de código de muestra que puede incluir problemas de seguridad y errores;
  • reduciendo el número de situaciones estúpidas en las que un punto final resultó ser accesible desde el exterior y olvidó informarlo;
  • eliminando la necesidad de actualizar todos los servicios cada vez que se agrega un nuevo rol o derecho;
  • que los nuevos servicios siguen siendo simples, seguros y rápidos.

Conclusión


Istio permite a los equipos enfocar sus recursos en tareas críticas del negocio sin agregar gastos generales a los servicios, devolviéndoles el estado micro.

El artículo (en tres partes) proporcionó conocimientos básicos e instrucciones prácticas listas para comenzar a trabajar con Istio en proyectos reales.

PD del traductor


Lea también en nuestro blog:

Source: https://habr.com/ru/post/443668/


All Articles