Cuando pasas a administrar software enterprise te topas con un montón de términos nuevos, y casi todos tienen detrás un problema que alguna organización tuvo que resolver. Por eso, más que una guía, este post es una exploración histórica de esos problemas de identidad y de las tecnologías que fueron surgiendo, para empaparnos de ellos, hablar el mismo lenguaje y tener un marco teórico cuando salgan nuevos retos o requisitos.
El problema original
Digamos que tenemos una empresa con 100 empleados y 5 programas en sus computadoras que necesitan accesos para hacer su trabajo. Cada programa podría tener su propia lista de usuarios y contraseñas, lo que vuelve un infierno mantenerlo. Pero si nos fijamos, todos los sistemas, para ser usados, tienen que resolver las mismas tres preguntas:
- ¿Quién eres?
- ¿Lo puedes demostrar?
- ¿Qué tienes permitido hacer?
Seguramente ya conoces estas preguntas. Es lo que asociamos directamente con AuthN (autenticación) y AuthZ (autorización).
La solución más clara es tener un directorio central donde tenemos a todos los usuarios asociados con diferentes atributos, como nombre, correo, departamento y teléfono. Y a su vez le podemos dar una estructura de árbol para poder subdividir la organización de acuerdo con las necesidades.
Directorios
Como con todos los demás procesos que se pueden encontrar en varias empresas, se hizo una familia de estándares conocida como la serie X.500, que prácticamente define cómo se estructuran los directorios en forma de árbol.
- X.500: https://www.itu.int/rec/T-REC-X.500
- X.501: https://www.itu.int/rec/T-REC-X.501
- X.520: https://www.itu.int/rec/T-REC-X.520
- X.521: https://www.itu.int/rec/T-REC-X.521
Lo más importante que hay que saber de esto es que existe el DN o Distinguished Name, el cual es el nombre completo y único de una entrada en el directorio. Se ve raro, pero si lo piensan como un árbol, es la ruta desde una hoja hasta la raíz. Ejemplo: CN=Juan,OU=Ventas,DC=empresa,DC=com.
Otras siglas que puedes encontrar dentro del DN son estas:
- CN: Common name
- OU: Organizational unit
- DC: Domain component
- O: Organization
- C: Country
Si te fijas, la mayoría de los DN terminan en DC. Esto se debe a https://www.rfc-editor.org/info/rfc2247/, que propuso usar los dominios del DNS como parte del DN, ya que una organización tenía garantizado ser la única dueña de ese dominio.
Como última nota, nomás resalto que los DN de los certificados X.509 empiezan con un CN que es el dominio del certificado. Esto se debe a que este spec es para asociar una clave pública a una entrada del directorio mundial de X.500. El directorio nunca existió, pero el formato se quedó. Hoy el dominio se valida con el campo Subject Alternative Name (SAN) y el CN ya no se usa para eso.
LDAP
Por sí solo, el directorio no es nada más que una estructura de datos que nos ayuda a reflejar la realidad operativa de una organización. Lo realmente importante es que podamos responder preguntas con base en ese directorio, y aquí es donde podemos empezar a hablar de protocolos. Aquí entra el Lightweight Directory Access Protocol (LDAP), cuyo nombre, ahora que tenemos el contexto, dice exactamente qué hace.
- LDAP: https://www.rfc-editor.org/info/rfc4510/
- Operaciones de LDAP: https://www.rfc-editor.org/info/rfc4511/
Las dos operaciones más comunes que se hacen mediante LDAP son buscar un usuario (search) con algún tipo de query basado en los atributos que tiene dentro del directorio, o verificar una contraseña (bind). Obviamente hay más operaciones para administrarlo, pero usualmente estos sistemas son más de lectura que de escritura.
Cuando hacemos bind mediante LDAP, el sistema recibe la contraseña y la manda al servidor LDAP. Eso implica dos cosas:
- Cada sistema sigue viendo las contraseñas de todos los usuarios, lo cual tiene riesgo de hackeo
- Por cada login en cada sistema, LDAP tiene que hacer un bind, es decir, el usuario tiene que iniciar sesión una vez por cada programa que use
Kerberos
Para resolver esto necesitamos que la contraseña solo la pueda ver una parte de confianza, no cada sistema, y, de alguna manera, que Juan inicie sesión una vez y tenga acceso a todos los sistemas. Esto segundo se conoce como Single Sign On (SSO).
Para eso usamos Kerberos, un protocolo de autenticación. Dentro de Kerberos podemos encontrar el Key Distribution Center (KDC), el cual es el único que guarda las llaves derivadas de las contraseñas. Una vez que verifica tu identidad, Kerberos te regresa un ticket. El ticket es un concepto clave en Kerberos: no es simplemente una respuesta, sino una credencial que incluye:
- Quién eres
- Para qué sistema es
- Cuándo se emitió
- Cuándo caduca
Luego le entregamos un ticket a cada programa y con eso nos deja entrar, sin necesidad de guardar o recibir una contraseña.
- Kerberos Protocolo: https://www.rfc-editor.org/rfc/rfc4120
- Kerberos API: https://www.rfc-editor.org/rfc/rfc4121
flowchart TB
PC["<b>PC de Juan</b><br/>Guarda tickets"]
subgraph S["Servidor central"]
direction LR
KDC["<b>KDC</b><br/>Emite tickets"] --> DIR["<b>Directorio</b><br/>Usuarios y grupos"]
end
PC -->|"(1) Demuestra quién es (una vez al día)"| KDC
KDC -.->|"(2) Le entrega un ticket"| PC
PC -->|"(3) Ticket"| N["<b>Nómina</b>"]
PC -->|"(3) Ticket"| C["<b>Correo</b>"]
PC -->|"(3) Ticket"| A["<b>Archivos</b>"]
Juan nunca le muestra la contraseña a ningún sistema, solo el ticket. En realidad hay dos tipos de tickets:
- Ticket Granting Ticket (TGT): este se obtiene al mero inicio. Cuando inicio sesión obtengo este, para poder generar tickets con los que ahora sí puedo iniciar sesión en aplicaciones
- Service Ticket: estos son los tickets que les mando directamente a las aplicaciones para iniciar sesión
Esto nos permite usar la contraseña solo una vez al día, debido a que en AD el TGT tiene una expiración de 10 horas por default.
La manera en que se cifran estos tickets es mediante un secreto compartido entre el KDC y las aplicaciones en las que puedes iniciar sesión. Cada aplicación tiene su propio secreto. Aquí se usa cifrado simétrico. Y aunque alguien se robe un ticket, no le sirve solo.
Dato curioso: Kerberos usa la hora para que nadie pueda reusar mensajes viejos, así que si el reloj de tu computadora tiene más de 5 minutos de diferencia con el servidor, no puedes iniciar sesión.
Active Directory
Con todo esto en su lugar, ahora podemos entender Active Directory (AD). Este no es más que un producto de Microsoft que empaqueta todos estos programas en uno. El servidor donde corre AD se llama Domain Controller (DC), el cual tiene un directorio, LDAP, KDC, DNS, replicación y policies (GPO).
Hasta ahora solo tenemos una manera segura de demostrar quién eres dentro de una organización. Ahora falta saber qué tantos permisos tienes dentro de ella. Para lograr esto se incluyeron varias piezas:
- Se crearon los Security Identifiers (SID): cada usuario y grupo tiene un SID, un número único e inmutable
- Se empezaron a incluir los SID en los tickets: el del usuario y los de los grupos a los que pertenece
- Cada recurso se daba de alta y tenía una lista de permisos mediante una Access Control List (ACL), la cual dice qué permisos tienen los grupos y las personas sobre el recurso
Entonces, dentro de los programas o servicios en los que ya podías iniciar sesión con tickets vivían recursos, y eran estos programas los que decidían qué podías hacer con ellos. AD solo les pasaba la lista, nunca tomaba la decisión.
AD es un programa tan configurable y tan robusto que podemos encontrar un spec completo para un solo feature. Por ejemplo:
- AD: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/d2435927-0999-4c62-8c6d-13ba31a52e1a
- AD Kerberos: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/2a32282e-dd48-4ad9-a542-609804b02cc9
- AD Ticket SIDs: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/
Y hay muchos más, para la replicación, las policies, los atributos, etc.
Por último, en AD “dominio” puede significar dos cosas. Primero, el nombre DNS del dominio, como corp.empresa.com (lo que ya no se recomienda es inventarse uno como empresa.local que solo existe dentro de la red privada). Segundo, un conjunto de usuarios, equipos y grupos que comparten el mismo directorio y confían en los mismos Domain Controllers.
Internet
Pero entonces llegó el internet. AD está diseñado para un escenario donde todos los empleados, PCs y servidores viven en la misma red interna de la oficina, y gracias al internet eso cambió. Salieron varios problemas, como:
- La PC se tiene que poder conectar al DC, y la VPN no siempre era una alternativa
- En varias redes hay firewalls que solo dejan pasar HTTP (80) o HTTPS (443), no Kerberos (88) ni LDAP (389)
- Compartir claves con todo el internet no escala, aparte de ser peligroso
- No hay forma sencilla de confiar en otras organizaciones
Los problemas 2 y 3 los podemos resolver mediante llaves públicas y privadas, ya que si los tokens van firmados, cualquiera puede verificarlos con la llave pública sin compartir secretos, y todo puede viajar por HTTPS. Por esto nacen nuevos estándares como SAML, OAuth 2.0 y OIDC, que veremos al final.
Y ahora sí, aquí entra Entra ID, antes conocido como Azure Active Directory, un servicio en la nube que cumple dos funciones: ser un directorio y un emisor de tokens. Este introdujo un término nuevo, el tenant, que es una organización dentro de Entra ID: mi propio directorio privado, separado del de cualquier otra empresa. Usualmente sigue el patrón empresa.onmicrosoft.com. Si queremos comparar AD con Entra ID, las equivalencias son las siguientes:
| Active Directory | Entra ID |
|---|---|
| Dominio | Tenant |
| Domain Controller (DC) | Infraestructura administrada por Microsoft |
| KDC | Emisor de tokens (login.microsoftonline.com) |
| TGT | Primary Refresh Token (PRT) |
| Service Ticket | Access token |
| Cifrado simétrico | Firma con llave pública/privada |
| SID | Object ID |
| SIDs de grupos en el ticket | Grupos incluidos en el token |
| LDAP | Microsoft Graph API |
| GPO | Intune |
| Puertos 88 (Kerberos) y 389 (LDAP) | Puerto 443 (HTTPS) |
Entra ID casi no usa LDAP ni Kerberos, y ahora podemos agregar pasos extra antes de recibir los tokens, como MFA. Además, como todo viaja por HTTPS, la PC ya no necesita ver al DC ni una VPN para iniciar sesión, lo que resuelve el problema 1.
Con esto ya podemos explicar lo que obtengo cuando compro una suscripción de M365 para mi organización:
- Un tenant en Entra ID, que es mi directorio y mi emisor de tokens
- Un conjunto de servicios (Exchange, SharePoint, Teams)
Entonces, cuando queremos entrar, por ejemplo, a Teams, lo que va a pasar es que la app de Teams le pide un access token a Entra ID (si ya inicié sesión, lo obtiene sin pedirme la contraseña). Luego lo manda a la API de Teams, que verifica la firma con la clave pública de Entra ID y finalmente decide qué puedo ver.
Federación
Nos queda el problema 4: confiar en otras organizaciones. A esto se le llama federación, y significa que una aplicación acepta las identidades que emite otra organización, sin tener que crear sus propias cuentas. Por ejemplo, cuando entras a Slack o a Salesforce con tu cuenta de la empresa, Slack nunca ve tu contraseña: confía en lo que le dice Entra ID.
Aquí es donde entran los estándares que mencionamos:
- SAML: el estándar enterprise clásico, basado en XML, con el que una aplicación confía en el proveedor de identidad de tu organización para iniciar sesión
- OAuth 2.0: no es para autenticar sino para autorizar, es decir, darle permiso a una aplicación de acceder a recursos en tu nombre
- OIDC (OpenID Connect): una capa sobre OAuth 2.0 que sí agrega autenticación, y es lo que hay detrás del botón “Iniciar sesión con Microsoft”
- JWT: no es un protocolo, sino el formato de los tokens firmados que usan OIDC y Entra ID
Cada uno de estos da para su propio post, así que aquí lo dejamos.