# Seguridad

## Resumen de Seguridad de GBDS

GBDS posee un módulo de seguridad que utiliza tokens JWT para realizar autenticación y autorización de usuarios. GBDS puede integrarse con cualquier directorio de usuarios compatible con LDAP para la autenticación, y con Apache Ranger para proporcionar auditoría de autorización y acceso.

### Componentes

Hay cuatro componentes principales que trabajan juntos para proporcionar seguridad a las operaciones de GBDS: Módulo de Seguridad del API, Ranger, Solr y el Almacenamiento de Credenciales LDAP.

* Módulo de Seguridad del API

  > Todas las solicitudes a la API pasan primero por el módulo de seguridad, que aplica autenticación y autorización para recursos protegidos.
* Almacenamiento de Credenciales LDAP

  > Una instancia LDAP (como Active Directory, OpenLDAP) mantiene información sobre usuarios y grupos de usuarios, y proporciona autenticación para acceder a la API de GBDS y autorizar las transacciones de la API.
* Ranger

  > Apache Ranger es un framework de seguridad que proporciona un control de acceso fino a la API de GBDS. Se pueden crear políticas de seguridad para bloquear o permitir accesos a los *endpoints* de la API basadas en criterios como grupo de usuario, nombre de usuario, recursos solicitados, métodos HTTP usados y dirección IP.
* Solr

  > GBDS usa Solr para almacenar registros de acceso de todas las solicitudes a la API; a través del panel de control de Ranger, estos registros pueden verse, buscarse y exportarse.

### Flujos de Trabajo Habilitados para Seguridad

#### Autenticación

Hay dos métodos para autenticarse con la API. Cuando el cliente no posee un token válido, debe usarse autenticación por credenciales. En este caso, el cliente realiza una petición al endpoint de creación de token, enviando un *payload* JSON con las credenciales válidas para un usuario registrado en LDAP. A continuación, el Módulo de Seguridad crea un vínculo con el directorio LDAP, usando las credenciales del usuario de vinculación (Bind User, vea más abajo), y realiza la autenticación. Luego, crea un Sujeto Autenticado: un usuario asociado con todos los grupos a los que pertenece. Finalmente, el Módulo de Seguridad construye un token JWT, lo firma digitalmente y lo devuelve al cliente. Este token puede usarse para realizar solicitudes posteriores a la API de GBDS.

![Flujo de Autenticación](https://974439850-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7Bx0xNdsdGHpCZ20yxbn%2Fuploads%2Fgit-blob-988f662bf52390fef00be3173057a37534737fe3%2Fauthenticationflow1.png?alt=media)

Cuando el cliente ya tiene un token válido, pero próximo a expirar, es posible usar ese token para crear uno nuevo con un tiempo de expiración posterior. Primero el cliente hace una solicitud al endpoint de creación de token con el token válido. El Módulo de Seguridad validará el token y creará uno nuevo, usando el mismo Sujeto Autenticado, pero con un nuevo *expirationTime*. El nuevo token será enviado al usuario. Como este flujo no requiere consultar el directorio LDAP, es mucho más rápido. Las aplicaciones cliente deben diseñarse para usar la renovación de token siempre que sea posible.

![Flujo de Autenticación](https://974439850-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7Bx0xNdsdGHpCZ20yxbn%2Fuploads%2Fgit-blob-c217f1d4f6725a32a646c4a9b6d6e6f98dafcc06%2Fauthenticationflow2.png?alt=media)

#### Realizando una Solicitud de API

Cuando se adquiere un token JWT válido, se envía a la API de GBDS con cada solicitud, siguiendo el estándar JWT. La solicitud tendrá un encabezado de autorización con el esquema *Bearer*, es decir, `Authorization: Bearer <token>`. Para recursos protegidos, el Módulo de Seguridad extraerá el token del encabezado y validará su firma usando la Clave de Firma original. Si el token es válido, la solicitud queda autenticada. A continuación, el Módulo de Seguridad construirá un *AuthorizationContext* con el nombre del sujeto, grupo del sujeto, recursos de la solicitud, dirección IP y método HTTP. Este *AuthorizationContext* será enviado a Ranger para autorizar o denegar la solicitud y será registrado por Solr, junto con sus resultados: *Permitido* o *Denegado*. Finalmente, si la solicitud es autorizada, será encaminada a la API de GBDS para su procesamiento.

![Realizando una Solicitud a la API](https://974439850-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7Bx0xNdsdGHpCZ20yxbn%2Fuploads%2Fgit-blob-337f3237c69dc6e8111e0ba5b970470781dee851%2Fapirequest.png?alt=media)

### Configuraciones

#### Archivos

El módulo de seguridad utiliza cuatro archivos de configuración diferentes:

* `/etc/griaule/conf/gbscluster.properties`: Archivo primario de configuración de GBDS. Cuando la seguridad está activa, las opciones de seguridad se configuran en este archivo.
* `/etc/griaule/conf/gbsapi/keystore.jks`: *Keystore* protegido por contraseña que contiene la **Ldap Bind User Password** y **JWT Signing Key**. Solo accesible por el usuario griaule.
* `/etc/griaule/conf/gbsapi/truststore`: *Truststore* protegido por contraseña que contiene la **Ldap Server Certificate** para permitir conexiones LDAP. Solo accesible por el usuario griaule.
* `/etc/griaule/conf/gbsapi/.password`: Archivo de contraseñas que contiene las contraseñas de *keystore* y *truststore*. Las contraseñas se almacenan en texto claro, y solo deberían ser accesibles por el usuario griaule.

#### Opciones de Seguridad

GBDS puede funcionar con o sin la seguridad activada, y esto se controla mediante la clave de configuración booleana: `gbscluster.api.security.enabled`. Cuando esta clave está definida como *false*, toda la seguridad queda deshabilitada y todas las demás claves de seguridad se ignoran. Si está definida como *true*, las siguientes claves de configuración **DEBEN** también deberán configurarse:

**Generales**

* `gbscluster.api.security.keystore`: ruta al *keystore* generado a partir del script de generación del *keystore*
* `gbscluster.api.security.truststore`: ruta al *truststore* que contiene el certificado del servidor LDAP. Requerido para usar LDAPS.
* `gbscluster.api.security.passwords`: ruta al archivo que contiene las contraseñas del *truststore* y *keystore*. Este archivo debe tener acceso restringido al usuario griaule.

**Autenticación**

* `gbscluster.api.security.ldap.url`: URL de conexión al servidor de almacenamiento de usuarios LDAP.
* `gbscluster.api.security.ldap.userSearchBase`: Nombre Distinguido/Distinguished Name (DN) del repositorio de usuarios en el servidor LDAP. Ejemplo: `ou=Users,dc=pd,dc=griaule`
* `gbscluster.api.security.ldap.userSearchAttribute`: Atributo de usuario que será usado como nombre de usuario durante la autenticación. Ejemplo: `sAMAccountName`, `uid`
* `gbscluster.api.security.ldap.userGroupMembershipAttribute`: Atributo de usuario que contiene la información de pertenencia a grupos. Ejemplo: `memberOf`
* `gbscluster.api.security.ldap.bindUserDN` Nombre distinguido del usuario de vinculación (Bind User). El usuario de vinculación es una cuenta de usuario usada por GBDS para enlazarse al servidor LDAP, autenticar usuarios y obtener sus grupos.

**Token**

* `gbscluster.api.security.token.ttlInMilliseconds`: Tiempo de vida, en milisegundos, del token JWT. Valores válidos: entre 30 minutos y 3 horas.

**Autorización**

* `gbscluster.api.security.authorization.ranger.configurationDirectory`: Directorio con las configuraciones específicas de Ranger para GBDS.

## Integrando con Active Directory

### Verificando Resolución de DNS

Antes de comenzar, asegúrese de que la resolución de nombres para el dominio en el que las máquinas del cluster serán integradas funciona correctamente. Para el dominio llamado pd.griaule, use el siguiente comando:

```sh
dig -t SRV _ldap._tcp.pd.griaule
```

{% hint style="info" %}
Asegúrese de que la SECCIÓN DE RESPUESTA está presente y contiene el nombre de host y la dirección IP del controlador de dominio.
{% endhint %}

{% hint style="warning" %}
**Resuelva cualquier problema de resolución DNS antes de continuar.**
{% endhint %}

### Instalando los Paquetes Necesarios

```sh
sudo yum install realmd sssd oddjob oddjob-mkhomedir adcli sssd-ad sssd-tools
```

### Integrando con el AD

Usar la utilidad *realm* es la forma más conveniente de integrar SSSD con AD. Ejecute el siguiente comando para mostrar la información básica sobre el dominio:

```sh
realm discover <domain_name>
```

#### Unirse al Dominio

Para unirse, necesitará una cuenta que pertenezca al grupo de administradores del dominio.

```sh
sudo realm join -U <username> <domain_name>
```

Luego, habilite NSS y PAM con:

```sh
authconfig --enablesssd --update
```

Y, finalmente, verifique que la máquina se haya unido al dominio correctamente consultando un usuario del dominio:

```sh
id <username>@<domain_name>
```

#### Solucionando Errores

Si surge algún problema, use los siguientes consejos:

* Verifique de nuevo la resolución de nombres DNS. Esta es la causa más frecuente de errores.
* Asegúrese de que los directorios `/etc/sssd/` y `/etc/sssd/conf.d` existen y ambos tienen permiso 0600.
* Aumente el debug\_level en `/etc/sssd/sssd.conf` en todas las secciones, es decir, `[sssd]`, `[nss]`, `[pam]`, `[domain]`. Luego, reinicie el servicio sssd: `sudo service sssd restart`. Los registros se generarán en la carpeta `/var/log/sssd/`
* En el caso del error `Insufficient permission to join the domain ...`: el usuario usado para unirse al dominio no tiene permiso. Verifique si el usuario forma parte del `Domain Admins group`

## Integrando con OpenLdap

Esta guía explica cómo realizar la instalación **mínima** de OpenLDAP que será compatible con GBDS para autenticación y autorización.

### Instale OpenLdap

#### Dependencias

Conéctese al host LDAP e instale los paquetes necesarios:

```sh
sudo yum -y install openldap compat-openldap openldap-clients openldap-servers openldap-servers-sql openldap-devel
```

#### Inicie el Demonio LDAP

A continuación, inicie el Demonio LDAP y configure para que arranque automáticamente al iniciar el sistema:

```sh
systemctl start slapd.service

systemctl enable slapd.service
```

#### Genere la contraseña de root

Ejecute el comando `ldappasswd` para crear una contraseña root de LDAP. Anote tanto la contraseña normal como la versión codificada devuelta por `ldappasswd`.

```sh
sudo slappasswd
```

#### Cree la base de datos hdb

El *hdb* es una variante jerárquica del backend de base de datos bdb. En el modelo de configuración abajo, defina las siguientes variables de acuerdo con su caso de uso:

* **olcSuffix**: Representa el nombre de dominio para el cual el LDAP proporcionará la información de cuentas. Además, este nombre distinguido será agregado a las *queries* que serán enviadas al backend.
* **olcRootDN**: es el nombre distinguido del usuario que tendrá acceso administrativo al servidor LDAP.
* **olcRootPW**: Define la contraseña del usuario administrador. La contraseña será el resultado codificado del comando `slappasswd`, que se ejecutó previamente.

Coloque la configuración en un archivo llamado `db.ldif`.

{% hint style="warning" %}
**ASEGÚRESE DE SUSTITUIR olcRootPW, olcRootDN y olcSuffix.**
{% endhint %}

```default
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=oldap,dc=pd,dc=griaule

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=ldapadm,dc=oldap,dc=pd,dc=griaule

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}theHashedPasswordValueFromSlapPasswd
```

{% hint style="warning" %}
Asegúrese de que no haya espacios innecesarios ni líneas en blanco, o podrían ocurrir problemas. Vea: <https://serverfault.com/questions/578710/wrong-attributetype-when-using-ldapadd>
{% endhint %}

Envíe los cambios al servidor

```sh
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f db.ldif
```

{% hint style="warning" %}
Si no usa *sudo*, tendrá problemas de permisos: `ldap_modify: Insufficient access (50)`
{% endhint %}

#### Restringir el Acceso de Monitoreo a ldapadm

Coloque las siguientes configuraciones en el archivo llamado `monitor.ldif` y actualice el `dn.base`, donde dice *UPDATE ME*, con el nombre distinguido del valor definido previamente en `oclRootDN`.

```default
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external, cn=auth" read by dn.base="UPDATE ME" read by * none
```

Envíe los cambios al servidor

```sh
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f monitor.ldif
```

{% hint style="warning" %}
Si no usa *sudo*, tendrá problemas de permisos: `ldap_modify: Insufficient access (50)`
{% endhint %}

#### Agregue el archivo de configuración del backend hdb

Este archivo define las opciones de configuración básicas para el backend hdb:

```sh
sudo cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
sudo chown ldap:ldap /var/lib/ldap/DB_CONFIG
```

#### Agregue esquemas LDAP esenciales

```sh
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
```

#### Habilite el módulo memberOf

{% hint style="warning" %}
**ES NECESARIO HACER ESTO ANTES DE QUE SE CREE CUALQUIER GRUPO. EL ATRIBUTO MEMBEROF ES UN ATRIBUTO OPERACIONAL Y NO SE CREA RETROACTIVAMENTE.**
{% endhint %}

Este módulo es necesario para consultar los grupos de un usuario. Coloque la siguiente configuración en el archivo llamado `memberof_config.ldif`:

```default
dn: cn=module,cn=config
cn: module
objectclass: olcModuleList
objectclass: top
olcmoduleload: memberof.la
olcmodulepath: /usr/lib64/openldap

dn: olcOverlay={0}memberof,olcDatabase={2}hdb,cn=config
objectClass: olcConfig
objectClass: olcMemberOf
objectClass: olcOverlayConfig
objectClass: top
olcOverlay: memberof
olcMemberOfDangling: ignore
olcMemberOfRefInt: TRUE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf
```

Para enviar los cambios al servidor, ejecute el comando:

```sh
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f memberof_config.ldif
```

#### Genere la base de datos para su dominio

Finalmente, especificamos la base de datos, que usará las configuraciones previamente creadas, para servir todas las solicitudes al dominio (valor de `olcSuffix`). Actualice el DN de *Users* y *Groups* para coincidir con las configuraciones del dominio. Inserte las configuraciones en `db_structure.ldif`.

```default
# Create entry for domain
dn: dc=oldap,dc=pd,dc=griaule
objectClass: domain
objectClass: top
dc: oldap

# Create an OU for Users
dn: ou=Users,dc=oldap,dc=pd,dc=griaule
objectClass: organizationalUnit
ou: Users

# Create an OU for Groups
dn: ou=Groups,dc=oldap,dc=pd,dc=griaule
objectClass: organizationalUnit
ou: Groups
```

Para enviar los cambios al servidor, use la cuenta de administrador configurada (`olcRootDN`) después del parámetro `-D`. La utilidad `ldapadd` pedirá la contraseña de la cuenta de administrador previamente definida.

```sh
sudo ldapadd -x -D 'cn=ldapadm,dc=oldap,dc=pd,dc=griaule' -W -H ldapi:/// -f db_structure.ldif
```

### Solucionando Errores

Tenga en cuenta que los mensajes de error devueltos por OpenLdap pueden ser confusos. Si tiene problemas con la instalación, se recomienda habilitar el modo debug. Pare el servicio slapd y luego reinicie directamente el proceso con la opción de debug `-d -1`:

```sh
slapd -d -1 -u ldap -h "ldap:/// ldapi:///"
```

Si TLS está habilitado, incluya también la cadena para el endpoint ldaps:

```sh
slapd -d -1 -u ldap -h "ldap:/// ldapi:/// ldaps:///"
```

### Cifrando contraseñas en OpenLdap

Por defecto, OpenLdap almacena las contraseñas en texto claro. Para cambiar este comportamiento, es necesario: [Definir un algoritmo global de hash](#configurando-o-algoritmo-hash) de contraseñas y [habilitar la política de contraseñas](#criando-uma-politica-de-senha-padrao) para cifrar automáticamente cualquier contraseña en texto claro.

#### Configurando el Algoritmo de Hash

Usaremos el algoritmo SHA-512 con 50000 rondas y sal de 16 bytes. Cree un archivo llamado `hash_algorithm.ldif`

```default
dn: cn=config
replace: olcPasswordHash
olcPasswordHash: {CRYPT}

dn: cn=config
replace: olcPasswordCryptSaltFormat
olcPasswordCryptSaltFormat: $6$rounds=50000$%.16s
```

Para enviar las configuraciones al servidor:

```sh
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f hash_algorithm.ldif
```

#### Importar el Esquema de Política de Contraseñas

```sh
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/ppolicy.ldif
```

#### Cargar el módulo de Política de Contraseñas

Cree un archivo llamado `password_policy_config.ldif` conteniendo:

```default
# load password policy module
dn: cn=module,cn=config
cn: module
objectClass: top
objectClass: olcModuleList
olcModuleLoad: ppolicy.la
olcModulePath: /usr/lib64/openldap

# apply the password policy overlay our database
dn: olcOverlay={1}ppolicy,olcDatabase={2}hdb,cn=config
objectClass: olcPPolicyConfig
objectClass: olcOverlayConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=Password Policy,ou=Policies,dc=oldap,dc=pd,dc=griaule
olcPPolicyForwardUpdates: FALSE
olcPPolicyHashCleartext: TRUE
olcPPolicyUseLockout: FALSE
```

Luego envíe los cambios con:

```sh
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f password_policy_config.ldif
```

Si encuentra un error indicando que pwdAttribute no existe, significa que el esquema de política de contraseñas no fue importado.

#### Creando una Política de Contraseña Predeterminada

Cree un archivo llamado `password_policy.ldif` conteniendo:

```default
# create default password policy
dn: cn=Password Policy,ou=Policies,dc=oldap,dc=pd,dc=griaule
objectClass: top
objectClass: device
objectClass: pwdPolicy
cn: Password Policy
```

Luego envíe los cambios con el comando abajo, reemplazando el `olcRootDN`:

```sh
sudo ldapadd -x -D '<olcRootDN>' -W -H ldapi:/// -f db_structure.ldif
```

### Mejorando la Seguridad

#### Desactivando Enlace Anónimo

Cree un archivo `disable_anon_binding.ldif` conteniendo:

```default
dn: olcDatabase={-1}frontend,cn=config
add: olcRequires
olcRequires: authc

dn: olcDatabase={2}hdb,cn=config
add: olcRequires
olcRequires: authc
```

Luego envíe los cambios:

```sh
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f disable_anon_binding.ldif
```

Para probar si los cambios funcionaron, ejecute la siguiente búsqueda anónima:

```sh
# without TLS
ldapsearch -x -LLL -H ldapi:/// "(cn=*)"
# Or with TLS
ldapsearch -x -LLL -H ldaps:/// "(cn=*)"
```

#### Desactivando Permiso de Lectura de Contraseñas de Usuario

Finalmente, cualquier usuario puede obtener la contraseña de otro usuario. Aunque las contraseñas estén cifradas, esto debe evitarse. Más aún si se decide mantener las contraseñas en texto claro. Entonces, cree un archivo llamado `disabled_password_read.ldif`.

{% hint style="warning" %}
**ASEGÚRESE DE QUE NO HAYA SALTOS DE LÍNEA PARA olcAccess**
{% endhint %}

```default
dn: olcDatabase={2}hdb,cn=config
add: olcAccess
olcAccess: to attrs=userPassword by dn="<olcRootDN>" write by self write by * auth
-
add: olcAccess
olcAccess: to * by dn="<olcRootDN>" write by users read by self write by * auth
```

Envíe los cambios:

```sh
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f disabled_password_read.ldif
```

Si ejecuta una búsqueda enlazada con cualquier usuario que no sea olcRootDN, la única contraseña devuelta será la del propio usuario.

```sh
ldapsearch -x -D '<non_root>' -LLL -H ldapi:/// "(cn=*)"
```

### Habilitando LDAPS

Antes de continuar, asegúrese de que su instancia de OpenLdap está funcionando y que posee dos unidades organizativas: una para usuarios y otra para grupos. Puede verificar esto usando Apache Directory Studio para conectar al servidor usando la URL de conexión ldap, por ejemplo: <ldap://192.168.0.100:389>, y con su cuenta de administrador configurada (**olcRootDN**).

Para habilitar LDAPS, será necesario un certificado válido firmado por una autoridad de confianza (trusted authority). Alternativamente, proveemos una guía de cómo configurar su propia autoridad certificadora y cómo usarla para firmar certificados de su servidor.

#### Cree su CA

Si ya tiene un certificado válido, puede omitir este paso.

En CentOS, encontrará el archivo `openssl.cnf`, que contiene la configuración principal para su CA, en el directorio `/etc/pki/tls`. Sin embargo, nuestra CA se ubicará en `/etc/pki/CA`.

Primero, cree el archivo `index.txt` y los archivos seriales, que contendrán información de los certificados firmados y el número de serie del certificado a usar, respectivamente.

```sh
touch /etc/pki/CA/index.txt
echo '01' > /etc/pki/CA/serial
```

A continuación, agregue las siguientes políticas a `/etc/pki/tls/openssl.cnf`:

```properties
# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ signing_policy ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
```

Ahora, cambie al directorio de la CA:

```sh
cd /etc/pki/CA
```

Generaremos el certificado CA, válido por 10 años, con el comando siguiente. La utilidad le pedirá que defina la contraseña de la clave privada y la información sobre el sujeto del certificado (la CA, en este caso). Anote esta contraseña, se requerirá para firmar certificados.

```sh
openssl req -config /etc/pki/tls/openssl.cnf -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 3650
```

A continuación, limite los permisos de acceso a la clave privada de la CA:

```sh
chmod 0400 private/cakey.pem
```

#### Cree un Certificado para el Servidor LDAP

Primero, creamos una solicitud de firma de certificado para el servidor LDAP:

```sh
openssl req -config /etc/pki/tls/openssl.cnf -newkey rsa:2048 -nodes -sha256 -out ldap_cert.csr -outform PEM -keyout ldap_key.pem
```

Luego, firmamos el `server.csr` usando la clave privada de la CA:

```sh
openssl ca -config /etc/pki/tls/openssl.cnf -policy signing_policy -extensions signing_req -out ldap_cert.pem -infiles ldap_cert.csr
```

Ahora, el `ldap_cert.pem` es el certificado para su servidor y su clave privada está en el archivo `ldap_key.pem`.

{% hint style="info" %}
la clave privada del servidor no está cifrada (`-nodes` parámetro). Esto es menos seguro, pero **OpenLdap no soporta claves cifradas**. Por lo tanto, es indispensable restringir todo acceso a ese archivo, como se hará en los pasos siguientes.
{% endhint %}

#### Configurando OpenLdap para usar el certificado y la clave

Primero, copie el certificado de la CA a `/etc/openldap/cacerts`. Esto hará que OpenLdap confíe en el certificado firmado por su CA.

```sh
mkdir /etc/openldap/cacerts
cp /etc/pki/CA/cacert.pem  /etc/openldap/cacerts
chown -R ldap:ldap /etc/openldap/cacerts/
```

Luego, instale el certificado de su servidor ldap en `/etc/openldap/certs`:

```sh
mv /etc/pki/CA/ldap_cert.pem /etc/openldap/certs
chown ldap:ldap /etc/openldap/certs/ldap_cert.pem

mv /etc/pki/CA/ldap_key.pem /etc/openldap/certs
chown ldap:ldap /etc/openldap/certs/ldap_key.pem
chmod 400 /etc/openldap/certs/ldap_key.pem
```

Establecer permiso 400 para la clave privada del servidor es **INDISPENSABLE**.

Cree un archivo llamado `enable_ldaps.ldif` con las siguientes configuraciones:

```default
dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/cacerts/cacert.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/ldap_cert.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/ldap_key.pem
```

Luego, envíe los cambios al servidor y pruebe los archivos de configuración:

```sh
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f enable_ldaps.ldif
```

#### Habilite el Endpoint TLS

En el archivo `/etc/sysconfig/slapd`, añada `ldaps:///` en la línea que comienza con `SLAPD_URLS=`. Después de esto, la línea debería ser similar a:

```properties
SLAPD_URLS="ldapi:/// ldap:/// ldaps:///"
```

#### Forzar TLS

Cree un archivo llamado `force_tls.ldif` con el siguiente contenido:

```default
dn: olcDatabase={2}hdb,cn=config
changetype:  modify
add: olcSecurity
olcSecurity: tls=1
```

Entonces, envíe los cambios al servidor:

```sh
sudo ldapmodify -v -Y EXTERNAL -H ldapi:/// -f force_tls.ldif
```

Ahora pruebe el requisito TLS ejecutando la siguiente búsqueda. Debe ser denegada debido al requisito TLS:

```sh
ldapsearch -H ldap://<host> -D "cn=ldapadm,dc=oldap,dc=pd,dc=griaule" -W '(uid=ldapadm)'
```

{% hint style="warning" %}
A PARTIR DE AHORA, CUALQUIER LLAMADA AL `ldapi:///` QUE REQUIERA EL *olcRootDN* (p. ej., aquellas que crean entidades en el árbol del directorio) DEBE REALIZARSE EN EL `ldaps:///`. LLAMADAS QUE PUEDEN USAR `-Y EXTERNAL` (p. ej., que modifica `cn=config`) TODAVÍA PUEDEN USAR `ldapi:///`.
{% endhint %}

#### Configuración TLS del lado del cliente

Para permitir que utilidades como `ldapsearch` se conecten vía TLS, agregue `TLS_REQCERT allow` a `/etc/openldap/ldap.conf`:

```sh
echo "TLS_REQCERT allow" >> /etc/openldap/ldap.conf
```

### Crear un Usuario Binding para el Ranger del GBDS

El GBDS y el Ranger exigirán que el usuario se vincule al servidor LDAP para ejecutar consultas y autenticaciones. El único privilegio que este usuario necesita es leer el árbol de directorio.

{% hint style="warning" %}
No use el olcRootDN como el usuario de enlace.
{% endhint %}

Cree un archivo llamado `bind_user.ldif` con el siguiente contenido. **Reemplace** o `dn:` por uno que coincida con su instalación. Adicionalmente, defina la contraseña del usuario de enlace. Si habilita el cifrado de la contraseña, escriba la contraseña en texto plano. Si no, use slappasswd para producir un hash para la contraseña y escriba el hash en el archivo `.ldif` (Similar a cómo se creó la contraseña de **olcRootDN**).

```default
dn: cn=gbds_bind,ou=Users,dc=oldap,dc=pd,dc=griaule
objectClass: top
objectClass: person
objectClass: inetOrgPerson
cn: gbds_bind
uid: gbds.bind
sn: Bind User
userPassword: <password>
```

Envíe los cambios con:

```sh
# for tls enabled
ldapadd -D "<olcRootDN>" -W -H ldaps:/// -f bind_user.ldif
# without tls
ldapadd -D "<olcRootDN>" -W -H ldapi:/// -f bind_user.ldif
```

Para probar si el usuario fue creado correctamente, ejecute la siguiente búsqueda autenticándose con el usuario de enlace `credentials:his`

```sh
ldapsearch -D "<bind_user_dn>" -W -H ldaps:/// "(cn=gbds_bind)"
```

### API de LDAP

La API LDAP es una API proporcionada por Griaule para ayudar en la gestión de usuarios y grupos. Usted puede autenticar, crear, eliminar o modificar datos de usuarios y listar datos de usuarios y datos de grupos mediante la API.

{% hint style="info" %}
Si los archivos de la API no fueron proporcionados, contacte al Equipo de Soporte de Griaule.
{% endhint %}

La API completa puede ser accedida en [Api do LDAP](https://app.gitbook.com/s/MqtschPie46KAAzuKKeD/ldap).

{% hint style="warning" %}
La API funciona con seguridad SSL y es necesaria una truststore y keystore. Para más información sobre la creación de éstas, vea la sección [Configurando la Seguridad del GBDS](#configurando-a-segurança-do-gbds).
{% endhint %}

#### Configurando la API

Para instalar y configurar correctamente la API, siga los pasos:

1. Extraiga el paquete proporcionado.
2. En `/etc/griaule` cree el directorio `ldap`.
3. Mueva el directorio `conf` del paquete proporcionado al directorio `/etc/griaule/ldap`.
4. Mueva el `config.properties` al directorio `/etc/griaule/ldap`.
5. Abra el archivo `config.properties` y ajuste los parámetros de configuración de acuerdo con su entorno.
6. En `/var/lib/griaule` cree el directorio `ldap`.
7. Mueva el archivo `bs-ldap-api.jar` y el script `kill-api.sh` y `start-api.sh` al nuevo directorio.
8. Ejecute el script de inicio (start).

#### Creando Nuevos Usuarios y Grupos

Para crear un nuevo usuario, invoque [Create User](https://gitbook.griaule.com/apis/ldap/create#post-ldap-user). La API creará el usuario, la contraseña y los grupos a los que el usuario pertenece.

Si se requieren modificaciones en un usuario existente, invoque [Modify User Data](https://gitbook.griaule.com/apis/ldap/user#put-ldap-user-user).

Para recuperar datos del usuario, invoque [Get User Data](https://gitbook.griaule.com/apis/ldap/user#get-ldap-user-user).

Para añadir, modificar o eliminar grupos, acceda a `/etc/griaule/ldap/conf/group-list.json` y modifique el archivo según lo deseado. También puede ver todos los grupos invocando [List Groups](https://gitbook.griaule.com/apis/ldap/list#get-ldap-user-groups).

## Instalando el Ranger

Después de que OpenLdap o Active Directory estén configurados, puede procederse a la instalación del Ranger.

### Prerrequisitos

#### Instalando ambari-infra

Vaya al Ambari e instale el servicio Ambari-infra. Esto proporcionará una instancia de Solr para almacenar datos auditados para el Ranger.

#### Instale y Configure la Instancia MySQL

1. Instale una instancia de MySQL
2. Cree el usuario rangerdba y conceda los privilegios necesarios

   ```sql
   CREATE USER 'rangerdba'@'localhost' IDENTIFIED BY 'Rangerdba$1';

   GRANT ALL PRIVILEGES ON *.* TO 'rangerdba'@'localhost' IDENTIFIED BY 'Rangerdba$1' WITH GRANT OPTION;

   CREATE USER 'rangerdba'@'%' IDENTIFIED BY 'Rangerdba$1';

   GRANT ALL PRIVILEGES ON *.* TO 'rangerdba'@'%';

   GRANT ALL PRIVILEGES ON *.* TO 'rangerdba'@'%' IDENTIFIED BY 'Rangerdba$1' WITH GRANT OPTION;

   FLUSH PRIVILEGES;
   ```

   > Note que Rangerdba$1 es la contraseña para el usuario rangerdba. Sustituya por la contraseña deseada.
3. Pruebe si el usuario rangerdba fue creado con éxito: `mysql -u rangerdba -p`
4. Instale el conector MySQL: `yum install mysql-connector-java*`
5. Registre el conector con Ambari, ejecutando los siguientes comandos en el host con el servidor Ambari instalado: `ambari-server setup --jdbc-db=mysql --jdbc-driver=/usr/share/java/mysql-connector-java.jar`

### Instalando el Servicio del Ranger

Vaya al Ambari y agregue el servicio Ranger. Visite cada una de las siguientes pestañas de configuración antes de finalizar la instalación.

#### Ranger Admin

1. Deje el nombre de usuario de la BD del Ranger como `rangeradmin`. Ponga la contraseña que desee, pero guárdela para después.
2. Asegúrese de que las opciones `Setup Database` y `Database User` estén marcadas como `Yes`
3. Para el nombre de usuario DBA, use la cuenta de usuario creada en los pasos anteriores.

#### Información de Usuarios del Ranger

Este servicio importará usuarios y grupos en la base de datos del Ranger.

{% hint style="info" %}
A continuación, damos **SUGERENCIAS** para valores en varias opciones de configuración requeridas. Usted debe asegurarse de que correspondan a su implementación LDAP.
{% endhint %}

1. Cambie el *Sync Source* para el `Ldap/AD`
2. En la pestaña *Common Config*:
   1. **LDAP/AD URL**: Si la URL configurada aquí es para LDAPS, el certificado LDAPS necesitará ser importado en el truststore de usersync como se describe en la sección [Importar el Certificado Ldaps](#importar-o-certificado-ldaps)
   2. **Bind User**: Complete el usuario DN de enlace y la contraseña. El usuario solo necesita privilegio de lectura para el repositorio de Usuarios y Grupos.
3. En la pestaña *User Configs*:
   1. **Username Attribute**: atributos que almacenan el userName para el inicio de sesión. Para AD, **usualmente** `sAMAccountName` y para OpenLdap, `uid`.
   2. **User Search Base**: DN para el nodo que contiene el usuario que necesita ser sincronizado (Usuario AD).
4. En la pestaña *Group Configs*:
   1. **Group member Attribute**: Atributo de la entidad Grupo que almacena qué usuario pertenece a qué grupo, además de información sobre la asociación usuario-grupo. Es **usualmente** `member`
   2. **Group Name Attribute**: Atributo del grupo que contiene el nombre del grupo. **Usualmente** `cn`
   3. **Group Object Class**: Clase de la entidad de grupo. Para AD, es **usualmente** `group`, para OpenLdap es **usualmente** `groupOfNames`
   4. **Group Search Base**: con el nodo que contiene los grupos que necesitan ser sincronizados

#### Ranger Audit

1. Marque la opción `Audit to Solr`
2. Marque la opción `Solr Cloud`

### Verificación de la Instalación

#### Sincronización de Usuario

Vaya al sitio web del Ranger en `http://<host>:6080`, inicie sesión y vaya a *Settings*, y entonces, *Users/Groups*. Todos los usuarios y grupos de la *User/Group Search Base* deben estar presentes. Si no es así, ocurrió un problema con la sincronización de usuario. Verifique el registro en `/var/log/ranger/usersync/usersync.log` para identificar el error.

#### Solr Audit

Vaya a la UI de ambari-infra y verifique la existencia de la colección `ranger_audits`

### Habilitando la Integración del Ldap con TLS

Para habilitar que Ranger use LDAPS en lugar de LDAP, se deben hacer dos cambios. Primero, necesitamos actualizar la URL de conexión LDAP a la URL protegida por TLS. Segundo, necesitamos importar el certificado LDAPS.

#### Cambiando la URL de Conexión LDAP

Vaya, en Ambari, a *Ranger*, *Configs*, *Ranger User Info*, *Common Configs*. Cambie el LDAP/AD URL a `ldaps://<hostname>:636`

#### Importar el Certificado Ldaps

Si su repositorio LDAP está usando TLS, necesita importar su certificado en el *UserSync truststore* del ranger.

Para obtener la ubicación del *truststore*, vaya a Ambari, *Ranger*, *Configs*, *Advanced*, *Advanced ranger-ugsync-site*, `ranger.usersync.truststore.file`. Luego, use el keytool de Java para importar el certificado LDAPS en la *truststore*. Si la *truststore* ya existe, será necesaria una contraseña. Si no, anote la contraseña usada. La necesitará después.

```sh
sudo keytool -import -trustcacerts -alias $ALIAS -file $PATH_TO_YOUR_LDAPS_CERT -keystore /usr/hdp/current/ranger-usersync/conf/mytruststore.jks
```

A continuación, corrija el permiso y el propietario de la *truststore*.

```sh
sudo chmod 640 /usr/hdp/current/ranger-usersync/conf/mytruststore.jks
sudo chown ranger:ranger /usr/hdp/current/ranger-usersync/conf/mytruststore.jks
```

Si la *truststore* es nueva, vaya a Ambari, *Ranger*, *Configs*, *Advanced*, *Advanced ranger-ugsync-site* y defina las propiedades:

1. **ranger.usersync.truststore.file**: con la ruta absoluta a la *truststore*
2. **ranger.usersync.truststore.password**: contraseña para la *truststore*

#### Solucionando Errores

Si no es posible crear el SSLContext para la comunicación con el gestor de políticas, hay un problema con las credenciales y las claves del usersync. La única forma de resolver este problema es eliminar la *truststore* `/usr/hdp/current/ranger-usersync/conf/mytrustore.jks`, recrearla con el certificado LDAPS y actualizar la configuración de la contraseña en Ambari, *Ranger*, *Configs*, *Advanced ranger-usersync-site*

## Configurando la Seguridad del GBDS

Una vez que Ranger, Solr y el servidor LDAP estén instalados y configurados, podemos proceder con las configuraciones del GBDS.

### Creando el Keystore del GBDS

El keystore se usará para guardar las contraseñas de los usuarios vinculados y las claves de firma para los tokens JWT generados por la API.

Ejecute el script `/var/lib/griaule/gbsapi/scripts/create_keystore.py` pasando la ruta al nuevo almacén de claves y la ruta para crear el archivo de contraseñas. El script preguntará por la contraseña del usuario de enlace a guardar. Luego, el script creará el keystore con la contraseña del usuario de enlace y una clave de firma aleatoria. El keystore será protegido por una contraseña generada aleatoriamente, la cual será guardada en el archivo de contraseñas especificado. Por último, los archivos del keystore y de contraseñas tendrán los permisos cambiados a solo lectura.

```sh
python /var/lib/griaule/gbsapi/scripts/create_keystore.py --store_path /etc/griaule/conf/gbsapi/keystore.jks --password_file /etc/griaule/conf/gbsapi/.passwords
```

{% hint style="info" %}
El archivo de contraseñas contiene las contraseñas en texto plano. Por lo tanto, es indispensable que esto se mantenga en una ubicación segura con acceso permitido solamente al usuario *griaule*.
{% endhint %}

### Creando *trustore* para LDAPS

Si pretende conectarse a su servidor LDAP usando SSL, necesita importar el certificado del servidor a un *truststore* y configurar el GBDS para usarlo.

Suponiendo que el certificado del servidor se llame `server_cert.pem`, ejecute el siguiente comando y use una contraseña fuerte para el *truststore*:

```sh
sudo keytool -import -trustcacerts -alias ldap_server -file <certificate_file> -keystore /etc/griaule/conf/gbsapi/truststore
chown griaule:griaule /etc/griaule/conf/gbsapi/truststore
chmod 400 /etc/griaule/conf/gbsapi/truststore
```

Además de crear la *truststore*, este comando restringirá el acceso al usuario griaule. Luego, guarde la contraseña de la *truststore* en el archivo de contraseñas.

```sh
sudo -u griaule chmod u+w /etc/griaule/conf/gbsapi/.passwords && sudo -u griaule echo "truststore=<YOUR_PASSWORD>" >> /etc/griaule/conf/gbsapi/.passwords && sudo -u griaule chmod 400 /etc/griaule/conf/gbsapi/.passwords
```

### Actualizando el Archivo de Configuración

Edite el archivo `/etc/griaule/conf/gbscluster.properties` y modifique las siguientes propiedades:

1. **gbscluster.api.security.enabled**: defina como *true* para habilitar la seguridad.
2. **gbscluster.api.security.keystore**: ruta al keystore que usted creó (`/etc/griaule/conf/gbsapi/keystore.jks`)
3. **gbscluster.api.security.truststore**: ruta a la *truststore* que usted creó (`/etc/griaule/conf/gbsapi/truststore`)
4. **gbscluster.api.security.passwords**: ruta al archivo de contraseñas (`etc/griaule/conf/gbsapi/.passwords`)
5. **gbscluster.api.security.ldap.url**: URL del servidor LDAP, ejemplo: `ldap://<host>:389`. Si habilitó LDAPS, esto debe ser `ldaps://<host>:636`
6. **gbscluster.api.security.ldap.userSearchBase**: El DN del nodo del árbol que guarda los usuarios que estarán habilitados para autenticación en el GBDS. En su guía de instalación de OpenLdap, el DN debería ser: `ou=Users,dc=oldap,dc=pd,dc=griaule`

   > **ES NECESARIO QUE SEA EL MISMO DN CONFIGURADO EN RANGER**
7. **gbscluster.api.security.ldap.userSearchAttribute**: Atributo de la entidad Usuario que contiene el `userName`, que será usado durante la autenticación.

   > **ES NECESARIO QUE SEA EL MISMO CONFIGURADO EN RANGER**
8. **gbscluster.api.security.ldap.userGroupMembershipAttribute**: Atributo de la entidad Usuario que contiene el DN de los grupos a los que pertenece. Usualmente memberOf.

   > **ES NECESARIO QUE SEA EL MISMO CONFIGURADO EN RANGER**
9. **gbscluster.api.security.ldap.bindUserDN**: DN del usuario de enlace. Use el mismo configurado para Ranger.
10. **gbscluster.api.security.token.ttlInMilliseconds**: Tiempo de vida, en milisegundos, para el token JWT generado por la API. Los valores válidos están entre 30 minutos y 3 horas. Recomendamos 1 hora.

## Instalando el Servicio de Autorización del Ranger

Para instalar y ejecutar el servicio de autorización del Ranger, es necesario haber creado un usuario GBDS y un usuario ADMIN.

Para crear el usuario administrador, abra el archivo `administrator_group.ldif` en la carpeta `/etc/openldap` y agregue lo siguiente al archivo:

```default
dn: cn=administrator,ou=Groups,dc=oldap,dc=pd,dc=griaule
objectclass: groupofnames
cn: administrator
description: IT Security Group
# Add the group members all of which are assumed to exist under people
member: cn=gbds_bind,ou=Users,dc=oldap,dc=pd,dc=griaule
```

A continuación, en el archivo `gbds_user.ldif`, cree el usuario GBDS.

```default
dn: cn=gbds_user,ou=Groups,dc=oldap,dc=pd,dc=griaule
objectclass: groupofnames
cn: gbds_user
description: IT Security Group
# Add the group members all of which are assumed to exist under people
member: cn=gbds_bind,ou=Users,dc=oldap,dc=pd,dc=griaule
```

Aplique los cambios reiniciando Ranger a través de la GUI del Ambari.

```sh
sudo ldapadd -D "cn=ldapadm,dc=oldap,dc=pd,dc=griaule" -W -H ldapi:/// -f /etc/openldap/administrator_group.ldif
sudo ldapadd -D "cn=ldapadm,dc=oldap,dc=pd,dc=griaule" -W -H ldapi:/// -f /etc/openldap/gbds_user.ldif
```

{% hint style="info" %}
Si el TLS está activo, recuerde cambiar `ldapi:///` por `ldaps:///`.
{% endhint %}

Cuando los cambios se apliquen, ejecute el Servicio de autorización de Ranger.

```sh
java -jar /root/ranger-authorization-service-installer-1.0-SNAPSHOT-jar-with-dependencies.jar -admin_password 'Griaule.123' -admin_username admin -ranger_url http://127.0.0.1:6080
```

Para finalizar el proceso, actualice los Archivos XML del Ranger. Vaya a `/etc/griaule/conf/gbsapi/` y en el archivo `ranger-gbds-audit.xml`, modifique según:

```xml
<name>xasecure.audit.jpa.javax.persistence.jdbc.url</name>
<value>jdbc:mysql://127.0.0.1:3306/ranger_audit</value>

<name>xasecure.audit.kafka.broker_list</name>
<value>localhost:9092</value>

<name>xasecure.audit.solr.solr_url</name>
<value>http://localhost:6083/solr/ranger_audits</value>

<name>xasecure.audit.destination.solr.urls</name>
<value>http://localhost:8886/solr/ranger_audits</value>
```

Haga lo mismo para `ranger-gbds-security.xml`

```xml
<name>ranger.plugin.gbds.policy.rest.url</name>
<value>http://localhost:6080</value>
```

## Configurando el PHP LDAP Admin

PHP LDAP Admin es una herramienta para gestionar OPENLDAP vía GUI, es una alternativa al uso de la CLI. El usuario puede agregar/modificar/eliminar usuarios, grupos, roles, etc. vía GUI. Tenga en cuenta que esto no es necesario para que LDAP funcione.

Primero, instale las dependencias de PHPLDAPAdmin.

En `/etc/httpd/conf.d`, actualice el archivo `phpldapadmin.conf` con

```properties
# Require local
Require all granted
```

Y también actualice el archivo `config.php` en la carpeta `/etc/phpldapadmin` con

```php
servers->setValue('server','name','Local LDAP Server');
servers->setValue('server','host','127.0.0.1');
servers->setValue('server','port',389);
servers->setValue('server','base',array('dc=oldap,dc=pd,dc=griaule'));
servers->setValue('login','attr','dn');
```

Ejecute el siguiente comando para iniciar y habilitar los servicios HTTPD

```sh
$ systemctl enable httpd.service && systemctl start httpd.service && systemctl status httpd.service
```

Después de habilitar HTTPD, es necesario especificar las posibles actualizaciones. Si el firewall está activado, ejecute

```sh
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --reload
```

Y si SELinux está habilitado, ejecute

```sh
setsebool -P httpd_can_connect_ldap on
```

Valide la GUI de PHP LDAP Admin abriendo la interfaz en <http://localhost/ldapadmin> con el usuario (DN, por ejemplo, cn=ldapadm,dc=oldap,dc=pd,dc=griaule) y contraseña. Luego, haga clic en los menús desplegables y confirme si todos los usuarios y grupos están disponibles.
