Introducción a la Autorización de Kubernetes de Hashicorp Consul

Introducción a la Autorización de Kubernetes de Hashicorp Consul

Todo está correcto, después del lanzamiento Hashicorp Consul 1.5.0 a principios de mayo de 2019, en Consul se puede realizar la autorización de aplicaciones y servicios que se ejecutan en Kubernetes de manera nativa.

En esta guía, crearemos paso a paso POC (Prueba de concepto (Proof of concept, PoC — demostración de [viabilidad] de la concepción — nota del traductor), mostrando esta nueva función. Se espera que tengas conocimientos básicos sobre Kubernetes y Hashicorp’s Consul. Aunque puedes usar cualquier plataforma en la nube o un entorno local, en esta guía utilizaremos Google Cloud Platform.

Reseña

Si vamos a la documentación de Consul sobre su método de autorización, obtendremos una breve visión de su propósito y caso de uso, así como algunos detalles técnicos y una visión general de la lógica. Te recomiendo encarecidamente que la leas al menos una vez antes de continuar, ya que ahora voy a explicar y desglosar todo esto.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

Diagrama 1: Resumen oficial del método de autorización de Consul

Veamos en la documentación del método específico de autorización de Kubernetes.

Por supuesto, hay información útil allí, pero no hay una guía sobre cómo usar todo esto realmente. Así que, como cualquier persona sensata, recorres Internet en busca de una guía. Y luego... te encuentras con un fracaso. Eso pasa. Vamos a solucionarlo.

Antes de que pasemos a crear nuestro POC, volvamos a la revisión de los métodos de autorización de Consul (Diagrama 1) y aclaremos esto en el contexto de Kubernetes.

Arquitectura

En esta guía, vamos a crear un servidor Consul en una máquina separada, que interactuará con un clúster de Kubernetes con el cliente Consul instalado. Luego, crearemos nuestra aplicación ficticia en un pod y utilizaremos nuestro método de autorización configurado para leer desde nuestro almacén de clave/valor Consul.

El diagrama a continuación ilustra en detalle la arquitectura que estamos creando en esta guía, así como la lógica del método de autorización, que se explicará más adelante.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

Diagrama 2: Resumen del método de autorización en Kubernetes

Una pequeña nota: el servidor Consul no necesita estar fuera del clúster de Kubernetes para que esto funcione. Pero sí, puede estar en cualquier lugar.

Así que, tomando el diagrama resumido de Consul (Diagrama 1) y aplicándolo a Kubernetes, obtenemos el diagrama anterior (Diagrama 2), y aquí la lógica será la siguiente:

  1. A cada pod se le asignará una cuenta de servicio que contiene un token JWT, generado y conocido por Kubernetes. Este token también se inserta en el pod por defecto.
  2. Nuestra aplicación o servicio dentro del pod inicia un comando de inicio de sesión en nuestro cliente de Consul. En la solicitud de inicio de sesión también se incluirá nuestro token y se especificará el nombre especialmente creado método de autorización (tipo Kubernetes). Este paso número 2 corresponde al paso 1 del esquema de Consul (Esquema 1).
  3. Nuestro cliente de Consul luego enviará esta solicitud a nuestro servidor de Consul.
  4. ¡MAGIA! Es aquí donde el servidor de Consul verifica la autenticidad de la solicitud, recopila información sobre la identidad de la solicitud y la compara con cualquier regla predefinida asociada. A continuación, habrá otro esquema para ilustrarlo. Este paso corresponde a los pasos 3, 4 y 5 del esquema general de Consul (Esquema 1).
  5. Nuestro servidor de Consul genera un token de Consul con permisos según las reglas proporcionadas por nosotros para el método de autorización (las que hemos definido) respecto a la identidad que solicita. Luego enviará este token de vuelta. Esto corresponde al paso 6 del esquema de Consul (Esquema 1).
  6. Nuestro cliente de Consul redirige el token a la aplicación o servicio que lo solicitó.

Nuestra aplicación o servicio ahora puede utilizar este token de Consul para interactuar con nuestros datos de Consul, como lo han definido los privilegios del token.

¡La magia revelada!

Para aquellos de ustedes que no están satisfechos solo con un conejo de la chistera y quieren saber cómo funciona... déjenme "mostrarles cuán profunda es la madriguera del conejo.».

Como se mencionó anteriormente, nuestro "mágico" paso (Esquema 2: Paso 4) consiste en que el servidor de Consul verifica la autenticidad de la solicitud, recopila información sobre la solicitud y la compara con cualquier regla predefinida asociada. Este paso corresponde a los pasos 3, 4 y 5 del esquema general de Consul (Esquema 1). A continuación, se presenta un esquema (Esquema 3) cuyo objetivo es ilustrar lo que realmente sucede bajo el capó. del método de autorización específico de Kubernetes.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

Esquema 3: ¡La magia revelada!

  1. Como punto de partida, nuestro cliente de Consul redirige la solicitud de inicio de sesión a nuestro servidor de Consul con el token de la cuenta de Kubernetes y el nombre específico de la instancia del método de autorización que se creó anteriormente. Este paso corresponde al paso 3 en la explicación anterior del esquema.
  2. Ahora el servidor Consul (o líder) necesita verificar la autenticidad del token recibido. Por lo tanto, consultará con el clúster de Kubernetes (a través del cliente de Consul) y, si tiene los permisos correspondientes, determinaremos si el token es auténtico y a quién pertenece.
  3. Luego, la solicitud verificada se devuelve al líder de Consul, y en el servidor de Consul se busca la instancia del método de autorización con el nombre especificado de la solicitud de inicio de sesión (y tipo Kubernetes).
  4. El líder de Consul identifica la instancia del método de autorización especificada (si se encuentra) y lee el conjunto de reglas de enlace que están adjuntas a ella. Luego lee estas reglas y las compara con los atributos de identidad verificados.
  5. ¡Tada! Pasamos al paso 5 en la explicación anterior del esquema.

Ejecute Consul-server en una máquina virtual normal.

A partir de este momento, principalmente daré instrucciones para crear este POC, a menudo en puntos, sin frases explicativas completas. Como se mencionó anteriormente, utilizaré GCP para crear toda la infraestructura, pero puedes crear una infraestructura similar en cualquier otro lugar.

  • Inicie una máquina virtual (instancia / servidor).

Introducción a la Autorización de Kubernetes de Hashicorp Consul

  • Crea una regla para el firewall (grupo de seguridad en AWS):
  • Me gusta asignar el mismo nombre a la máquina que a la regla y la etiqueta de red, en este caso es 'skywiz-consul-server-poc'.
  • Encuentra la dirección IP de tu computadora local y agrégala a la lista de direcciones IP de origen para que podamos acceder a la interfaz de usuario (UI).
  • Abre el puerto 8500 para la interfaz de usuario. Haz clic en Crear. Pronto cambiaremos nuevamente este firewall [enlace].
  • Agrega una regla al firewall para la instancia. Regresa al panel de control de VM en el servidor Consul y agrega 'skywiz-consul-server-poc' en el campo de etiquetas de red. Haz clic en Guardar.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

  • Instala Consul en la máquina virtual, verifica aquí. Recuerda que necesitas una versión de Consul ≥ 1.5 [enlace]
  • Crearemos un Consul de nodo único; la configuración es la siguiente.

groupadd --system consul
useradd -s /sbin/nologin --system -g consul consul
mkdir -p /var/lib/consul
chown -R consul:consul /var/lib/consul
chmod -R 775 /var/lib/consul
mkdir /etc/consul.d
chown -R consul:consul /etc/consul.d

  • Guía más detallada sobre la instalación de Consul y la configuración de un clúster de 3 nodos en. aquí.
  • Crea el archivo /etc/consul.d/agent.json de la siguiente manera [enlace]:

### /etc/consul.d/agent.json
{
 "acl" : {
 "enabled": true,
 "default_policy": "deny",
 "enable_token_persistence": true
 }
}

  • Ejecuta nuestro servidor Consul:

consul agent 
-server 
-ui 
-client 0.0.0.0 
-data-dir=/var/lib/consul 
-bootstrap-expect=1 
-config-dir=/etc/consul.d

  • Deberías ver un montón de salida y al final “… actualizaciones bloqueadas por ACLs”.
  • Encuentra la dirección IP externa del servidor Consul y abre un navegador en esa dirección IP en el puerto 8500. Asegúrate de que se abra la interfaz de usuario.
  • Intenta agregar un par clave/valor. Debería haber un error. Esto se debe a que hemos cargado el servidor Consul con ACL y prohibido todas las reglas.
  • Regresa a tu terminal en el servidor Consul y ejecuta el proceso en segundo plano o de otra manera, para que se esté ejecutando, y escribe lo siguiente:

consul acl bootstrap

  • Encuentra el valor 'SecretID' y regresa a la interfaz de usuario. En la pestaña 'ACL', introduce el identificador secreto del token que acabas de copiar. Copia el SecretID en otro lugar, lo necesitaremos más tarde.
  • Ahora agrega un par clave/valor. Para este POC, añadiremos lo siguiente: clave: 'custom-ns/test_key', valor: '¡Estoy en la carpeta custom-ns!'

Iniciando un clúster de Kubernetes para nuestra aplicación con el cliente Consul como Daemonset.

  • Crea un clúster K8s (Kubernetes). Lo crearemos en la misma zona que el servidor, para un acceso más rápido, y así podemos usar la misma subred para una conexión sencilla con direcciones IP internas. Lo llamaremos 'skywiz-app-with-consul-client-poc'.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

  • Como nota, aquí tienes una buena guía con la que me encontré al configurar el POC del clúster Consul con Consul Connect.
  • También usaremos el gráfico helm de Hashicorp con un archivo de valores extendido.
  • Instala y configura Helm. Pasos de configuración:

kubectl create serviceaccount tiller --namespace kube-system
kubectl create clusterrolebinding tiller-admin-binding 
   --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
. /helm init --service-account=tiller
. /helm update

### poc-helm-consul-values.yaml
global:
 enabled: false
 image: "consul:latest"
# Expose the Consul UI through this LoadBalancer
ui:
 enabled: false
# Allow Consul to inject the Connect proxy into Kubernetes containers
connectInject:
 enabled: false
# Configure a Consul client on Kubernetes nodes. GRPC listener is required for Connect.
client:
 enabled: true
 join: ["<PRIVATE_IP_CONSUL_SERVER>"]
 extraConfig: |
{
  "acl" : {
 "enabled": true,   
 "default_policy": "deny",   
 "enable_token_persistence": true 
  }
}
# Minimal Consul configuration. Not suitable for production.
server:
 enabled: false
# Sync Kubernetes and Consul services
syncCatalog:
 enabled: false

  • Aplica el gráfico helm:

. /helm install -f poc-helm-consul-values.yaml . /consul-helm - name skywiz-app-with-consul-client-poc

  • Al intentar iniciarlo, necesitará permisos para el servidor Consul, así que vamos a añadirlos.
  • Observa el 'rango de direcciones Pod' ubicado en el panel del clúster y regresa a nuestra regla para el firewall 'skywiz-consul-server-poc'.
  • Agrega el rango de direcciones para los pods a la lista de direcciones IP y abre los puertos 8301 y 8300.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

  • Ve a la interfaz del Consul, y después de unos minutos verás que nuestro clúster aparecerá en la pestaña de nodos.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

Configuración del método de autorización integrando Consul con Kubernetes.

  • Vuelve a la terminal del servidor Consul y exporta el token que guardaste anteriormente:

export CONSUL_HTTP_TOKEN=

  • Necesitaremos información de nuestro clúster de Kubernetes para crear una instancia del método de autenticación:
  • kubernetes-host

kubectl get endpoints | grep kubernetes

  • kubernetes-service-account-jwt

kubectl get sa -consul-client -o yaml | grep "- name:"
kubectl get secret  -o yaml | grep token:

  • El token está codificado en base64, así que descífralo con tu herramienta favorita [enlace]
  • kubernetes-ca-cert

kubectl get secret  -o yaml | grep ca.crt:

  • Toma el certificado "ca.crt" (después de decodificarlo de base64) y escríbelo en el archivo "ca.crt."
  • Ahora crea una instancia del método de autenticación, reemplazando los placeholders con los valores que acabas de obtener.

consul acl auth-method create 
-type "kubernetes" 
-name "auth-method-skywiz-consul-poc" 
-description "Este es un método de autenticación utilizando Kubernetes para el clúster skywiz-app-with-consul-client-poc" 
-kubernetes-host="" 
-kubernetes-ca-cert=@ca.crt 
-kubernetes-service-account-
jwt=""

  • A continuación, debemos crear una regla y adjuntarla a un nuevo rol. Para esta parte, puedes usar la interfaz de usuario de Consul, pero usaremos la línea de comandos.
  • Escribe la regla

### kv-custom-ns-policy.hcl
key_prefix "custom-ns/" {
 policy = "write"
}

  • Aplica la regla

consul acl policy create 
-name kv-custom-ns-policy 
-description "Este es un ejemplo de política para kv en custom-ns/" 
-rules @kv-custom-ns-policy.hcl

  • Encuentra el identificador de la regla que acabas de crear en la salida.
  • Crea un rol con la nueva regla.

consul acl role create 
-name "custom-ns-role" 
-description "Este es un ejemplo de rol para el espacio de nombres custom-ns" 
-policy-id

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='custom-ns-role' 
-selector='serviceaccount.namespace=="custom-ns"'

Configuraciones finales

Accesos

  • Crea accesos. Necesitamos otorgar permiso a Consul para verificar e identificar el token de credenciales de la cuenta de servicio K8s.
  • Escribe lo siguiente en el archivo [enlace]:

###skywiz-poc-consul-server_rbac.yaml
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: review-tokens
 namespace: default
subjects:
- kind: ServiceAccount
 name: skywiz-app-with-consul-client-poc-consul-client
 namespace: default
roleRef:
 kind: ClusterRole
 name: system:auth-delegator
 apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: service-account-getter
 namespace: default
rules:
- apiGroups: [""]
 resources: ["serviceaccounts"]
 verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: get-service-accounts
 namespace: default
subjects:
- kind: ServiceAccount
 name: skywiz-app-with-consul-client-poc-consul-client
 namespace: default
roleRef:
 kind: ClusterRole
 name: service-account-getter
 apiGroup: rbac.authorization.k8s.io

  • Crearemos accesos

kubectl create -f skywiz-poc-consul-server_rbac.yaml

Conexión al cliente de Consul

  • Como se mencionó aquí, hay varias opciones para conectarse al daemonset, pero pasaremos a la siguiente solución más sencilla:
  • Aplica el siguiente archivo [enlace].

### poc-consul-client-ds-svc.yaml
apiVersion: v1
kind: Service
metadata:
 name: consul-ds-client
spec:
 selector:
   app: consul
   chart: consul-helm
   component: client
   hasDNS: "true"
   release: skywiz-app-with-consul-client-poc
 ports:
 - protocol: TCP
   port: 80
   targetPort: 8500

  • Luego aplica el siguiente comando integrado para crear el configmap [enlace]. Ten en cuenta que nos referimos al nombre de nuestro servicio, cámbialo si es necesario.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
 labels:
   addonmanager.kubernetes.io/mode: EnsureExists
 name: kube-dns
 namespace: kube-system
data:
 stubDomains: |
   {"consul": ["$(kubectl get svc consul-ds-client -o jsonpath='{.spec.clusterIP}')"]}
EOF

Prueba del método de autenticación

¡Ahora veamos la magia en acción!

  • Cree algunas carpetas clave más con la misma clave de nivel superior (es decir, /sample_key) y un valor de su elección. Cree las políticas y roles correspondientes para las nuevas rutas clave. Haremos las vinculaciones más tarde.

Introducción a la Autorización de Kubernetes de Hashicorp Consul

Prueba del usuario del espacio de nombres:

  • Creamos nuestro propio espacio de nombres:

kubectl create namespace custom-ns

  • Creemos un pod en nuestro nuevo espacio de nombres. Escriba la configuración para el pod.

###poc-ubuntu-custom-ns.yaml
apiVersion: v1
kind: Pod
metadata:
 name: poc-ubuntu-custom-ns
 namespace: custom-ns
spec:
 containers:
 - name: poc-ubuntu-custom-ns
   image: ubuntu
   command: ["/bin/bash", "-ec", "sleep infinity"]
 restartPolicy: Never

  • Cree el pod:

kubectl create -f poc-ubuntu-custom-ns.yaml

  • Una vez que el contenedor esté en funcionamiento, ingrese y asegúrese de instalar curl.

kubectl exec poc-ubuntu-custom-ns -n custom-ns -it /bin/bash
apt-get update && apt-get install curl -y

  • Ahora enviaremos una solicitud de inicio de sesión a Consul usando el método de autorización que creamos anteriormente [enlace].
  • Para ver el token ingresado desde su cuenta de servicio:

cat /run/secrets/kubernetes.io/serviceaccount/token

  • Escriba lo siguiente en un archivo dentro del contenedor:

### payload.json
{
 "AuthMethod": "auth-method-test",
 "BearerToken": "<jwt_token>"
}

  • ¡Inicio de sesión!

curl 
--request POST 
--data @payload.json 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Para realizar los pasos anteriores en una sola línea (ya que realizaremos varias pruebas), puede hacer lo siguiente:

echo "{ 
"AuthMethod": "auth-method-skywiz-consul-poc", 
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)" 
}" 
| curl 
--request POST 
--data @- 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • ¡Funciona! Al menos debería. Ahora obtenga el SecretID y trate de acceder a la clave/valor al que deberíamos tener acceso.

curl 
consul-ds-client.default.svc.cluster.local/v1/kv/custom-ns/test_key --header “X-Consul-Token: ”

  • Puede decodificar «Value» en base64 y ver que coincide con el valor en custom-ns/test_key en la interfaz de usuario. Si utilizó el mismo valor que se muestra arriba en esta guía, su valor codificado será IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.

Prueba de la cuenta de servicio personalizada:

  • Cree una cuenta de servicio personalizada usando el siguiente comando [enlace].

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
 name: custom-sa
EOF

  • Cree un nuevo archivo de configuración para el pod. Tenga en cuenta que incluí la instalación de curl para ahorrar esfuerzo 🙂

###poc-ubuntu-custom-sa.yaml
apiVersion: v1
kind: Pod
metadata:
 name: poc-ubuntu-custom-sa
 namespace: default
spec:
 serviceAccountName: custom-sa
 containers:
 - name: poc-ubuntu-custom-sa
   image: ubuntu
   command: ["/bin/bash","-ec"]
   args: ["apt-get update && apt-get install curl -y; sleep infinity"]
 restartPolicy: Never

  • Después de eso, inicie una shell dentro del contenedor.

kubectl exec -it poc-ubuntu-custom-sa /bin/bash

  • ¡Inicio de sesión!

echo "{ 
"AuthMethod": "auth-method-skywiz-consul-poc", 
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)" 
}" 
| curl 
--request POST 
--data @- 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Permiso denegado. Oh, olvidamos agregar un nuevo enlace de regla con los permisos correspondientes, hagámoslo ahora.

Repita los pasos anteriores:
a) Cree una Política idéntica para el prefijo "custom-sa/".
b) Cree un Rol, llámelo "custom-sa-role"
c) Asocie la Política al Rol.

  • Cree un Rule-Binding (solo se puede hacer desde cli/api). Tenga en cuenta el valor diferente de la bandera selector.

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='custom-sa-role' 
-selector='serviceaccount.name=="custom-sa"'

  • Vuelva a iniciar sesión desde el contenedor "poc-ubuntu-custom-sa". ¡Éxito!
  • Verifique nuestro acceso a la ruta clave custom-sa/.

curl 
consul-ds-client.default.svc.cluster.local/v1/kv/custom-sa/test_key --header "X-Consul-Token: "

  • También puede asegurarse de que este token no proporciona acceso a kv en "custom-ns/". Simplemente repita el comando anterior después de reemplazar "custom-sa" con el prefijo "custom-ns".
    Permiso denegado.

Ejemplo de superposición:

  • Cabe destacar que todos los enlaces de rule-binding se agregarán al token con estos permisos.
  • Nuestro contenedor "poc-ubuntu-custom-sa" está en el espacio de nombres predeterminado, así que usemoslo para otro rule-binding.
  • Repita los pasos anteriores:
    a) Cree una Política idéntica para el prefijo de clave "default/".
    b) Cree un Rol, llámelo "default-ns-role"
    c) Asocie la Política al Rol.
  • Cree un Rule-Binding (solo se puede hacer desde cli/api)

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='default-ns-role' 
-selector='serviceaccount.namespace=="default"'

  • Regrese a nuestro contenedor "poc-ubuntu-custom-sa" y trate de acceder a la ruta "default/" kv.
  • Permiso denegado.
    Puede ver las credenciales asociadas a cada token en la UI en la sección ACL > Tokens. Como puede ver, a nuestro token actual solo se le ha asignado una "custom-sa-role". El token que estamos utilizando actualmente fue generado cuando iniciamos sesión, y en ese momento solo había un rule-binding que coincidía. Necesitamos volver a iniciar sesión y usar un nuevo token.
  • Asegúrese de que puede leer tanto desde las rutas "custom-sa/" como "default/" kv.
    ¡Éxito!
    Esto se debe a que nuestro "poc-ubuntu-custom-sa" coincide con los enlaces de reglas "custom-sa" y "default-ns".

Conclusión

¿Gestión de tokens TTL?

En el momento de escribir este artículo, no existe una forma integrada de determinar el TTL para los tokens generados por este método de autorización. Sería una gran oportunidad contar con automatización de autorización segura para Consul.

Existe la posibilidad de crear un token manualmente con TTL:

Espero que pronto podamos controlar cómo se generan los tokens (para cada regla o método de autorización) y agregar TTL.

Mientras tanto, se sugiere utilizar la lógica en el endpoint de cierre de sesión.

También lee otros artículos en nuestro blog:

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster