Skip to content

Revisión de Service Accounts

Es una cuenta de usuario que está destinada a ser utilizada por procesos dentro de pods, en lugar de por usuarios humanos. Estas cuentas proporcionan autenticación al API de Kubernetes para los procesos que se ejecutan en los pods, permitiendo a Kubernetes que administre sus permisos y acceda a los recursos de la API de manera controlada. En la mayoría de distirbuciones de kubernetes en cada namespace existe el service account: default, el cual es utilizado por todas las cargas de trabajo, si el atributo serviceAccountName no está definido en el recurso.

Cuando un usuario ingresa al cluster ya sea mediante la Interfaz o mediante comandos (kubectl), este obtiene una identidad mediante la autenticación con ese usuario, por lo que puede acceder e interactuar con el APIServer y sus componentes. Esto mismo sucede con los Service Account, la diferencia consiste que en el caso de un Service Account se limita a ciertas acciones dentro del mismo namespace donde se está ejecutando el proceso en cuestión.

Cada Service Account puede estar asignado a una lista de permisos en específico mediante Roles que definen las acciones permitidas sobre los diferentes grupos de componentes del APIServer, como por ejemplo el grupo asociado a los Deployments con acciones de ver, listar, crear pero no modificar o eliminar.

Guías Prácticas de Laboratorio

Antes de comenzar

  • Contar con el acceso al ambiente del laboratorio.

Conexión hacia cluster

  1. Ingrese al cluster asignado con las credenciales proporcionadas.

  2. Configure la variable KUBECONFIG.

    export KUBECONFIG=~/devcluster/kube_config_cluster.yml
    
  3. Verifique el acceso mediante comandos.

    kubectl get namespaces
    

Instalación de YQ

  1. Ingrese al cluster asignado con las credenciales proporcionadas.

  2. Descargue e instale el binario de YQ en el PATH requerido.

    curl -Lo yq https://github.com/mikefarah/yq/releases/download/v4.24.2/yq_linux_amd64 && sudo chmod +x ./yq && sudo mv yq /usr/bin/yq
    
  3. Verifique el binario instalado.

    yq -V
    

Guía 1: Service Account

Descripción

La presente guía muestra cómo crear, listar, modificar y eliminar Service Accounts dentro de un namespace.

Objetivos

  • Crear un Service Account personalizado
  • Autenticarse mediante un Token de Service Account
  • Modificar los permisos del Service Account mediante Roles
  • Verificar los permisos del Service Account

Inicio de laboratorio

  1. Crear un nuevo namespace llamado example-sa

    kubectl create ns example-sa
    

  2. Establecer el nuevo namespace por defecto con el contexto actual.

    kubectl config set-context --current --namespace=example-sa
    

  3. Liste los Service Accounts del namespace actual.

    kubectl get sa
    

  4. Obtenga la información del SA default.

    kubectl describe sa default
    

  5. Desde Kubernetes v1.24 los secrets para los SA deben ser generados manualmente, por lo tanto crearemos el siguiente YAML.

    cat > example-sa/secret.yaml <<-EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: robot-token
      namespace: example-sa
      annotations:
        kubernetes.io/service-account.name: default
    type: kubernetes.io/service-account-token
    EOF
    

  6. Luego crearemos el recurso secret con lo siguiente.

    kubectl apply -f example-sa/secret.yaml
    

  7. Verifique los Secrets del namespace actual

    kubectl get secrets
    
    Nota: El concepto de Secret se verá en otro tópico. Un Secret es un recurso de Kubernetes que permite almacenar datos considerados como credenciales y son utilizados por Aplicaciones y Herramientas, en este caso es utilizado para almacenar el token del ServiceAccount.

  8. Obtenga la información del Secret robot-token.

    kubectl describe secret robot-token
    
    El Token del ServiceAccount es utilizado para comunicarse contra el APIServer, para mantener el estado y la configuración del recurso.

  9. Obtener los diferentes contextos que se tienen configurados en el archivo kubeconfig

    kubectl config get-contexts
    
    Nota: Anote el nombre del contexto que está utilizando actualmente

  10. Cree una entrada de usuario para kubectl utilizando el contenido descifrado del campo token para autenticarse contra el cluster

    kubectl config set-credentials sa-user --token=$(kubectl get secret robot-token -o jsonpath={.data.token} | base64 -d)
    

  11. Cambie el usuario que utiliza para kubectl.

    kubectl config set-context local --user=sa-user
    

  12. Verifique los usuarios que tiene para kubectl.

    kubectl config get-users
    

  13. Pruebe a obtener los Pods del namespace.

    kubectl get pods
    
    Nota: Esta parte debe tirar un error de permisos.

  14. Pruebe a obtener los Namespaces del cluster.

    kubectl get ns
    
    Nota: Esta parte debe tirar un error de permisos.

  15. Configure nuevamente kubectl para ocupar las credenciales de su usuario.

    kubectl config set-context local --user=kube-admin-local
    

  16. Cree un Service Account llamado list-only.

    kubectl create sa list-only
    

  17. Cree un Role que permita obtener la lista de pods en el namespace actual.

    kubectl create role pod-reader --verb=get --verb=list --resource=pods
    

  18. Cree un RoleBinding para el Service Account list-only.

    kubectl create rolebinding list-pods-sa-binding --role=pod-reader --serviceaccount=example-sa:list-only
    

  19. Verifique que los recursos Role y RoleBinding existan en el namespace.

    kubectl get roles,rolebindings
    

  20. Verifique la información del Service Account list-only.

    kubectl describe sa list-only
    

  21. Cree el siguiente YAML para el Token del Service Account anterior.

    cat > example-sa/secret-list-only.yaml <<-EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: list-only-token
      namespace: example-sa
      annotations:
        kubernetes.io/service-account.name: list-only
    type: kubernetes.io/service-account-token
    EOF
    

  22. Luego crearemos el recurso Secret con lo siguiente.

    kubectl apply -f example-sa/secret-list-only.yaml
    

  23. Obtenga el nombre del Secret a utilizar.

    kubectl get secrets
    

  24. Obtener los diferentes contextos que se tienen configurados en el archivo kubeconfig

    kubectl config get-contexts
    
    Nota: Anote el nombre del contexto que está utilizando actualmente

  25. Cree una entrada de usuario para kubectl utilizando el contenido descifrado del campo token para autenticarse contra el cluster

    kubectl config set-credentials sa-user-list-only --token=$(kubectl get secret list-only-token -o jsonpath={.data.token} | base64 -d)
    

  26. Cambie el usuario que utiliza para kubectl.

    kubectl config set-context --current --user=sa-user-list-only
    

  27. Verifique que pueda obtener el listado de Pods

    kubectl get pods
    

  28. Verifique que los demás accesos estén restringidos (debe dar error)

    kubectl get ns
    
    kubectl get secrets
    

  29. Configure nuevamente kubectl para ocupar las credenciales de su usuario

    kubectl config set-context local --user=kube-admin-local
    

  30. Limpie el ambiente

    kubectl delete ns example-sa
    

  31. Configure el namespace a utilizar por el contexto de kubectl a default

    kubectl config set-context --current --namespace=default
    

Guía 2: Exploración de Token

Descripción

Por cada Namespace existe un Service Account por defecto llamado default el cual es asignado a los Pods que no especifiquen el parámetro serviceAccount o serviceAccountName. Cada SA genera un Secret que contiene el token con el cual se autentica y el certificado del CA del cluster para trust.

Podemos configurar permisos sobre los diferentes recursos tal cual se hace con una cuenta normal de Usuario, de esta forma podemos ampliar su uso a través de desarrollo propio.

Objetivos

  • Crear un Service Account Token
  • Validar el acceso al API de Kubernetes Utilizando el Token
  • Crear Token con expiración por defecto (1 hora)
  • Crear Token con expiración de (24 horas)
  • Examinar Token (https://jwt.io/)

Inicio del Laboratorio

Sección 1

  1. Crear un nuevo namespace llamado explore-sa

    kubectl create ns explore-sa
    

  2. Establecer el nuevo namespace por defecto con el contexto actual

    kubectl config set-context --current --namespace=explore-sa
    

  3. Liste los Service Accounts.

    kubectl get sa
    

  4. Cree un nuevo Service Account.
    kubectl create sa robot
    
  5. Revise la información del SA creado.
    kubectl describe sa robot
    
  6. Elimine el SA.
    kubectl delete sa robot
    
  7. Crear un nuevo namespace llamado explore-sa.
    kubectl create ns explore-sa
    
  8. Crearemos el siguiente directorio siguiente manera:
    mkdir example-sa
    
  9. Luego crearemos un archivo sa.yaml de la siguiente manera.
    cat > example-sa/sa.yaml <<-EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: robot
      namespace: explore-sa
    EOF
    
  10. Cree el SA usando el archivo YAML.
    kubectl apply -f example-sa/sa.yaml
    
  11. Solicite un token para ese service account.
    kubectl create token robot
    
  12. Tome el valor de ese token y examinarlo en el sitio: https://jwt.io/. ⚠ NO REALICE ESTO CON UN TOKEN DE PRODUCCION ⚠

JWT-Site

  1. Valide los campos:
Nombre Descripción
iat Issued At
exp Expiration Time

Sección 2

  1. Obtenga el valor de server de la configuración de su cluster de RKE.

    SERVER=$(yq ".clusters[0].cluster.server" ~/devcluster/kube_config_cluster.yml)
    

  2. Valide el valor de la variable

    echo $SERVER
    
    Mostrará algo similar a: https://*******:6443
    

  3. Defina la variable de ambiente TOKEN

    TOKEN='VALOR_TOKEN_OBTENIDO_EN_PASOS_ANTERIORES'
    

  4. Intente consumir el API de Kubernetes sin el token

    curl -k ${SERVER}/version
    

  5. Examinar Resultado

    {
      "kind": "Status",
      "apiVersion": "v1",
      "metadata": {},
      "status": "Failure",
      "message": "Unauthorized",
      "reason": "Unauthorized",
      "code": 401
    }
    

  6. Note el error 401 Unauthorized paso anterior.

  7. Intente consumir el API de Kubernetes utilizando el token.

    curl -k -H "Authorization: Bearer ${TOKEN}"  ${SERVER}/version
    

  8. Examinar Resultado

    {
      "major": "1",
      "minor": "24",
      "gitVersion": "v1.24.10",
      "gitCommit": "5c1d2d4295f9b4eb12bfbf6429fdf989f2ca8a02",
      "gitTreeState": "clean",
      "buildDate": "2023-01-18T19:08:10Z",
      "goVersion": "go1.19.5",
      "compiler": "gc",
      "platform": "linux/amd64"
    }
    

  9. Cree un pod de prueba en el namespace explore-sa.

    kubectl run nginx --image=nginx
    kubectl get pods
    

  10. Verifique que el pod haya sido creado.

    kubectl get pods
    

  11. Intente obtener los recursos tipo pods en el namespace explore-sa Utilizando el API.

    curl -k -H "Authorization: Bearer ${TOKEN}"  ${SERVER}/api/v1/namespaces/explore-sa/pods
    

  12. Examinar Resultado:

    {
      "kind": "Status",
      "apiVersion": "v1",
      "metadata": {},
      "status": "Failure",
      "message": "pods is forbidden: User \"system:serviceaccount:explore-sa:robot\" cannot list resource \"pods\" in API group \"\" in the namespace \"explore-sa\"",
      "reason": "Forbidden",
      "details": {
        "kind": "pods"
      },
      "code": 403
    }
    

  13. Note el error 403 Forbidden paso anterior.

Sección 3

  1. Crear un Rol a nivel de Kubernetes, que permita get,list a los recursos tipo pods en el namespace explore-sa.

    kubectl create role get-pods-sa --verb get,list --resource=pods
    

  2. Consulte el rol creado.

    kubectl describe role get-pods-sa
    

  3. Asigar el rol get-pods-sa al serviceAccount robot en el namespace explore-sa.

    kubectl create rolebinding allow-sa-pods --role get-pods-sa --serviceaccount=explore-sa:robot
    

  4. Intente obtener los recursos tipo pods en el namespace explore-sa utilizando el API.

    curl -k -H "Authorization: Bearer ${TOKEN}" ${SERVER}/api/v1/namespaces/explore-sa/pods
    

  5. Examinar Resultado. Obtendra un json con la información de todos los pods de ese namespace

Sección 4

El token generado en el inicio del laboratorio tiene una duración por defecto de 1 hora.

Podemos modificar ese tiempo en la creación del token utilizando la opción --duration=TIEMPO.

Ejemplo: --duration=24h

Para crear un TOKEN para un Service Account, el cual podemos utilizar sin vencimiento, podemos crear un secret con una anotación que hace referencia a un token.

  1. Crear el siguinete manifiesto.

    cat <<EOF > secret-token-robot.yaml
    apiVersion: v1
    kind: Secret
    type: kubernetes.io/service-account-token
    metadata:
      name: robot
      annotations:
        kubernetes.io/service-account.name: "robot"
    EOF
    

  2. Crear el recurso en el cluster.

    kubectl create -f secret-token-robot.yaml
    

  3. Listar los recursos tipo secret.

    kubectl get secrets
    

  4. Obtener token desde el secret y decodifiquelo de base64.

    TOKEN2=$(kubectl get secret -o jsonpath="{.data.token}" robot|base64 --decode)
    

  5. Depliegue el valor del token.

    cat $TOKEN2
    

  6. Tome el valor de ese token y examinarlo en el sitio: https://jwt.io/. ⚠ NO REALICE ESTO CON UN TOKEN DE PRODUCCION :warning.

JWT-Site

  1. Note que no tiene vencimiento. La única forma de invalidarlo es eliminando el secret y creando uno nuevo.

  2. Intente obtener los recursos tipo pods en el namespace explore-sa Utilizando el API y el nuevo TOKEN2.

    curl -k -H "Authorization: Bearer ${TOKEN2}"  ${SERVER}/api/v1/namespaces/explore-sa/pods
    

  3. Examinar Resultado: Obtendra un json con la información de todos los pods de ese namespace

  4. Elimine el Secret token

    kubectl delete -f secret-token-robot.yaml
    

  5. Intente obtener los recursos tipo pods en el namespace explore-sa Utilizando el API y el nuevo TOKEN2.

  6. Examinar Resultado:

    {
      "kind": "Status",
      "apiVersion": "v1",
      "metadata": {},
      "status": "Failure",
      "message": "Unauthorized",
      "reason": "Unauthorized",
      "code": 401
    }
    

  7. Note el error 401 Unauthorized paso anterior.

  8. Limpiamos el ambiente.

    kubectl delete pod nginx --force --grace-period=0
    kubectl delete rolebindings allow-sa-pods
    kubectl delete role get-pods-sa
    kubectl delete ns explore-sa
    kubectl config set-context --current --namespace=default --user=kube-admin-local
    

Sección 5 - Reto

Realice las adaptaciones necesarias en estas guias para realizar las consultas utilizando el proxy de Rancher para el cluster de Kubernetes

TIP: Vea un kubeconfig descargado desde Rancher Server