Asegurando el acceso a nuestros Clusters Kubernetes con Teleport

Si no saben lo que es Teleport y por que me gusta, tal vez leyendo esta entrada se den cuenta. No solo encontrarán la explicación del producto, si no que tambien sabran conectarse a servidores, internos, de manera segura.

Instalación de Teleport

Casi todas las organizaciones tienen más de un Cluster de Kubernetes, vamos a acceder de una manera sencilla vía Teleport. Algunas cosas que vamos a parametrizar, por un lado tenemos que poner nuestro correo para el Challange de LetsEncrypt y el nombre del Cluster, que no será ni más ni menos que el FQDN que queremos que sea alcanzado de manera pública.

helm install teleport-cluster \
--set acme=true \
--set acmeEmail=sfernandez@ironbox.com.ar \
--set clusterName=teleport.esprueba.com \
--create-namespace \
--namespace=teleport-cluster \
teleport/teleport-cluster

Ahora vemos el despliegue en nuestro Cluster, importante obtener la dirección de nuestro balanceador. En mi caso, es un Cluster Vanila por ende estoy usando Metallb.

Registro DNS

Es importante que nuestro registro DNS apunte a nuestro dirección pública. Para que funcione mi prueba de concepto, agregue el registro a mi DNS y luego abri el puerto 443 de mi firewall contra la dirección del balanceador. Si estas aca, leyendo, esto lo sabes hacer. Les hago un paneo de las configuraciones.

¿Cómo conocer mi direccion ip, publica?

curl ifconfig.me
181.XX.XX.XX

Agregamos el registro.

Ahora el Port Forwarding.

Podemos decir que tenemos nuestro Teleport configurado, listo para usar. Para tenerlo 100% funcionando, debemos abrir los demás puertos como el 3023, 3026, etc.

Vamos a crear un usuario para poder administrar Teleport, para ello nos vamos a guardar el ID del Pod, con el siguiente comando, y luego mostrarlo.

POD=$(kubectl get pod -l app=teleport-cluster -o jsonpath='{.items[0].metadata.name}' -n teleport-cluster)
> echo $POD
teleport-cluster-auth-6bfc69dfb9-tlw66

Ahora que sabemos que el Pod de autenticación es teleport-cluster-auth-6bfc69dfb9-tlw66, vamos a crear el usuario teleport-admin e ingresamos al link que nos arroja.

kubectl exec -ti ${POD?} -n teleport-cluster  -- tctl users add teleport-admin --roles=editor,access --logins=root,teleport-admin
User "teleport-admin" has been created but requires a password. Share this URL with the user to complete user setup, link is valid for 1h:
https://teleport.esprueba.com:443/web/invite/d193d90c789a2cc616251f337f0b7182

NOTE: Make sure teleport.esprueba.com:443 points at a Teleport proxy which users can access.

Vamos a configurar la cuenta, al final necesitaremos agregar el 2FA. Yo utilice Google Authenticator.

Ya tenemos lista nuestra cuenta, para ingresar. Una vez que realizamos el SingIn tenemos nuestro recurso disponible y listo para usar.

Aca los patrones de conexión al cluster.

Uala! Estamos listo para manejar nuestro cluster, de manera segura, desde el exterior.

Aca vemos la auditoría de Teleport, con los pasos que acabamos de realizar. Una buena idea sería enviar todos estos logs a un SIEM, para tener un IR sobre cualquier inconveniente que podríamos llegar a tener.

Agregar un nuevo Cluster

Para agregar otro cluster, tendríamos que generar un Token para hacer el Join a Teleport. Para ello, en el cluster que tiene Teleport.

> TOKEN=$(kubectl exec -ti "${POD?}" -n teleport-cluster -- tctl nodes add --roles=kube --ttl=10000h --format=json | jq -r '.[0]')
> echo $TOKEN
e67180614246d9c90bf230582b33f882

Ya tenemos el Token*e67180614246d9c90bf230582b33f882*, ahora tenemos que cargar las variables

export CLUSTER='minikube'
export PROXY='teleport.esprueba.com:443'
export TOKEN='e67180614246d9c90bf230582b33f882'

Hacemos un Switch sobre nuevo cluster, para poder instalar

helm install teleport-agent teleport/teleport-kube-agent --set kubeClusterName=${CLUSTER?} \
  --set proxyAddr=${PROXY?} --set authToken=${TOKEN?} --create-namespace --namespace=teleport-agent

Revisamos si levanto, en nuestro cluster minikube, el teleport-agent.

Cree un nuevo rol con privilegios kubernetes-admin.

kind: role
metadata:
  # insert the name of your role here:
  name: kubernetes-admin
spec:
  # This example defines a typical role. It allows listing all resources
  # with typical developer credentials.
  allow:
    # List of Kubernetes cluster users can access the k8s API
    kubernetes_labels:
      '*': '*'
    # This role is mapped to Kubernetes 'developer' group.
    kubernetes_groups:
    - '{{internal.kubernetes_groups}}'
    - developer
    - admin
    - system:masters
    kubernetes_users:
    - '{{internal.kubernetes_users}}'
    - 'dev'

    # List of Kubernetes resources users can access with this role
    # This example allows access to all resources in all namespaces
    kubernetes_resources:
    - kind: '*'
      namespace: '*'
      name: '*'
      verbs: ['*']

    # List of allowed SSH logins
    logins: ['{{internal.logins}}', ubuntu, debian]

    # List of node labels that users can SSH into
    node_labels:
      '*': '*'

    # List of application labels users can access
    app_labels:
      '*': '*'

    # List of database labels users can access database servers
    db_labels:
      '*': '*'
    # List of databases on the database server users can access
    db_names:
    - '{{internal.db_names}}'
    - '*'
    # List of database users allowed to open database connections with
    db_users:
    - '{{internal.db_users}}'
    - developer

    # List of windows desktop access labels that users can open desktop sessions to
    windows_desktop_labels:
      '*': '*'
    # Windows logins a user is allowed to use for desktop sessions.
    windows_desktop_logins:
    - '{{internal.windows_logins}}'
    - developer

    # RBAC rules for various resources within a cluster. This
    # example provides access to the Audit Log and replaying a user's own sessions.
    rules:
    - resources:
      - event
      verbs:
      - list
      - read
    - resources:
      - session
      verbs:
      - read
      - list
      where: contains(session.participants, user.metadata.name)

  # The 'deny' section can have settings that override their 'allow' counterparts
  # It uses the same format as the 'allow' section
  deny:
    logins: ['guest']

  options:
      # Limits user credentials to 8 hours. After the time to live (TTL) expires,
      # users must re-login
      max_session_ttl: 8h0m0s
version: v7

Ahora creamos un usuario que tenga estos derechos.

Una vez completado el registro, el usuario puede iniciar sesión en el portal.

En la sección Kubernetes, puede ver a qué clústeres Kubernetes tiene acceso, y haciendo clic en el botón de conexión obtendrá todas las instrucciones para conectarse con el Cluster Kubernetes que seleccione.

Cree un usuario llamado santiago con permisos sobre el rol kubernetes-admin, hare el SingUp y una vez conectado al Cluster de minikube listare los recursos.

Hay muchas maneras de aplicar permisos sobre este usuario, que puede y que no hacer. Esta documentación explica a detalle, cada permiso.

Estoy seguro que les será de utilidad.

0
Subscribe to my newsletter

Read articles from Santiago Fernandez directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Santiago Fernandez
Santiago Fernandez

I have a bachelor's degree in Technology from the University of Palermo, a Master in Information Security from the University of Murcia and different certifications such as CISSP | CISM | CDPSE | CCSK | CSX | MCSA | SMAC™️ | DSOE | DEPC | CSFPC | CSFPC | 5x AWS Certified. He is currently CISO at Klar, a Mexican Fintech. He was fortunate to be awarded as CISO of the Year in Argentina in 2021 and was among the Top 100 CISO's in the World in 2022. A lover of new technologies, he has developed a career in DevSecOps and Cloud Security at Eko Party, the largest security conference in Latin America.