# Security

## GBDS Security Overview

GBDS has a security module that uses JWT tokens to perform user authentication and authorization. GBDS can be integrated with any LDAP-compatible user directory for authentication, and with Apache Ranger to provide authorization and access auditing.

### Components

There are four main components that work together to provide security for GBDS operations: API Security Module, Ranger, Solr and the LDAP Credentials Store.

* API Security Module

  > All API requests first pass through the security module, which enforces authentication and authorization for protected resources.
* LDAP Credentials Store

  > An LDAP instance (such as Active Directory, OpenLDAP) maintains information about users and user groups, and provides authentication to access the GBDS API and authorize API transactions.
* Ranger

  > Apache Ranger is a security framework that provides fine-grained access control to the GBDS API. Security policies can be created to block or allow access to *endpoints* of the API based on criteria such as user group, username, requested resources, HTTP methods used and IP address.
* Solr

  > GBDS uses Solr to store access logs for all API requests; through the Ranger control panel these logs can be viewed, searched and exported.

### Security-Enabled Workflows

#### Authentication

There are two methods to authenticate with the API. When the client does not have a valid token, credential-based authentication must be used. In this case, the client makes a request to the token creation endpoint, passing a *payload* JSON with the valid credentials for a user registered in LDAP. Then, the Security Module creates a binding to the LDAP directory, using the bind user credentials (Bind User, see below), and performs authentication. It then creates an Authenticated Subject: a user associated with all the groups to which they belong. Finally, the Security Module builds a JWT token, digitally signs it and returns it to the client. This token can be used to make subsequent requests to the GBDS API.

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

When the client already has a valid token but it is near expiration, it is possible to use that token to create a new one with a later expiration time. First the client makes a request to the token creation endpoint with the valid token. The Security Module will validate the token and create a new one, using the same Authenticated Subject but with a new *expirationTime*. The new token will be sent to the user. Since this flow does not require querying the LDAP directory, it is much faster. Client applications should be designed to use token renewal whenever possible.

![Authentication Flow](https://3757157672-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7Bx0xNdsdGHpCZ20yxbn%2Fuploads%2Fgit-blob-c217f1d4f6725a32a646c4a9b6d6e6f98dafcc06%2Fauthenticationflow2.png?alt=media)

#### Making an API Request

When a valid JWT token is acquired, it is sent to the GBDS API with every request, following the JWT standard. The request will have an authorization header with the *Bearer*, that is, `Authorization: Bearer <token>`. For protected resources, the Security Module will extract the token from the header and validate its signature using the original Signing Key. If the token is valid, the request is authenticated. Next, the Security Module will build an *AuthorizationContext* with the subject name, subject groups, request resources, IP address and HTTP method. This *AuthorizationContext* will be sent to Ranger to authorize or deny the request and will be logged by Solr, along with its results: *Allowed* or *Denied*. Finally, if the request is authorized, it will be forwarded to the GBDS API for processing.

![Making an API Request](https://3757157672-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7Bx0xNdsdGHpCZ20yxbn%2Fuploads%2Fgit-blob-337f3237c69dc6e8111e0ba5b970470781dee851%2Fapirequest.png?alt=media)

### Logout.

#### Files

The security module uses four different configuration files:

* `/etc/griaule/conf/gbscluster.properties`: Primary GBDS configuration file. When security is enabled, security options are configured in this file.
* `/etc/griaule/conf/gbsapi/keystore.jks`: *Keystore* password-protected containing the **Ldap Bind User Password** and **JWT Signing Key**. Accessible only by the griaule user.
* `/etc/griaule/conf/gbsapi/truststore`: *Truststore* password-protected containing the **Ldap Server Certificate** to allow LDAP connections. Accessible only by the griaule user.
* `/etc/griaule/conf/gbsapi/.password`: Password file containing the passwords for the *keystore* and *truststore*. Passwords are stored in plain text, and it should only be accessible by the griaule user.

#### Security Options

GBDS can run with or without security enabled, and this is controlled by the boolean configuration key: `gbscluster.api.security.enabled`. When this key is set to *false*, all security is disabled and all other security keys are ignored. If set to *true*, the following configuration keys **MUST** must also be configured:

**General**

* `gbscluster.api.security.keystore`: path to the *keystore* generated from the generation script of the *keystore*
* `gbscluster.api.security.truststore`: path to the *truststore* which contains the LDAP server certificate. Required to use LDAPS.
* `gbscluster.api.security.passwords`: path to the file containing the passwords for the *truststore* and *keystore*. This file should have restricted access to the griaule user.

**Authentication**

* `gbscluster.api.security.ldap.url`: URL to connect to the LDAP user store server.
* `gbscluster.api.security.ldap.userSearchBase`: Distinguished Name (DN) of the user repository on the LDAP server. Example: `ou=Users,dc=pd,dc=griaule`
* `gbscluster.api.security.ldap.userSearchAttribute`: User attribute that will be used as the username during authentication. Example: `sAMAccountName`, `uid`
* `gbscluster.api.security.ldap.userGroupMembershipAttribute`: User attribute containing group membership information. Example: `memberOf`
* `gbscluster.api.security.ldap.bindUserDN` Distinguished name of the bind user (Bind User). The bind user is a user account used by GBDS to bind to the LDAP server, authenticate users and fetch their groups.

**Token**

* `gbscluster.api.security.token.ttlInMilliseconds`: Lifetime, in milliseconds, of the JWT token. Valid values: between 30 minutes and 3 hours.

**Authorization**

* `gbscluster.api.security.authorization.ranger.configurationDirectory`: Directory with GBDS-specific ranger settings.

## Integrating with Active Directory

### Checking DNS Resolution

Before starting, make sure name resolution for the domain in which the cluster machines will be integrated is working correctly. For the domain named pd.griaule, use the following command:

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

{% hint style="info" %}
Make sure the ANSWER SECTION is present and contains the hostname and IP address of the domain controller.
{% endhint %}

{% hint style="warning" %}
**Resolve any DNS resolution issues before continuing.**
{% endhint %}

### Installing Required Packages

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

### Integrating with AD

Using the *realm* utility is the most convenient way to integrate SSSD with AD. Run the following command to show basic information about the domain:

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

#### Join the Domain

To join, you will need an account that belongs to the domain administrators group.

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

Then, enable NSS and PAM with:

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

And, finally, verify that the machine successfully joined the domain by querying a user in the domain:

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

#### Troubleshooting Errors

If any problem arises, use the following tips:

* Recheck DNS name resolution. This is the most frequent cause of errors.
* Make sure the directories `/etc/sssd/` and `/etc/sssd/conf.d` exist and both have permission 0600.
* Increase the debug\_level in `/etc/sssd/sssd.conf` in all sessions, that is, `[sssd]`, `[nss]`, `[pam]`, `[domain]`. Then, restart the sssd service: `sudo service sssd restart`. Logs will be generated in the folder `/var/log/sssd/`
* In case of the error `Insufficient permission to join the domain ...`: the user used to join the domain does not have permission. Check that the user is part of the `Domain Admins group`

## Integrating with OpenLdap

This guide explains how to perform a **minimal** installation of OpenLDAP that will be compatible with GBDS for authentication and authorization.

### Install OpenLdap

#### Dependencies

Connect to the LDAP host and install the required packages:

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

#### Start Ldap Daemon

Next, start the LDAP Daemon and configure it to start automatically at system boot:

```sh
systemctl start slapd.service

systemctl enable slapd.service
```

#### Generate the root password

Run the command `ldappasswd` to create an LDAP root password. Write down both the plain password and the encoded version returned by `ldappasswd`.

```sh
sudo slappasswd
```

#### Create the hdb-database

The *hdb* is a hierarchical variant of the bdb database backend. In the configuration template below, set the following variables according to your use case:

* **olcSuffix**: Represents the domain name for which the LDAP will provide account information. Additionally, this distinguished name will be added to the *queries* that will be sent to the backend.
* **olcRootDN**: is the distinguished name of the user who will have administrator access to the LDAP server.
* **olcRootPW**: Sets the administrator user's password. The password will be the encoded result of the command `slappasswd`, which was executed previously.

Put the configuration in a file called `db.ldif`.

{% hint style="warning" %}
**MAKE SURE TO REPLACE olcRootPW, olcRootDN and 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" %}
Make sure there are no unnecessary spaces or blank lines, or problems may occur. See: <https://serverfault.com/questions/578710/wrong-attributetype-when-using-ldapadd>
{% endhint %}

Send the changes to the server

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

{% hint style="warning" %}
If you do not use *sudo*, you will have permission problems: `ldap_modify: Insufficient access (50)`
{% endhint %}

#### Restrict Monitoring Access to ldapadm

Put the following settings in a file called `monitor.ldif` and update the `dn.base`, where it says *UPDATE ME*, with the distinguished name of the value previously set for `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
```

Send the changes to the server

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

{% hint style="warning" %}
If you do not use *sudo*, you will have permission problems: `ldap_modify: Insufficient access (50)`
{% endhint %}

#### Add the hdb-backend configuration file

This file defines the basic configuration options for the hdb-backend:

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

#### Add essential LDAP schemas

```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
```

#### Enable the memberOf module

{% hint style="warning" %}
**THIS MUST BE DONE BEFORE ANY GROUP IS CREATED. THE MEMBEROF ATTRIBUTE IS AN OPERATIONAL ATTRIBUTE AND IS NOT CREATED RETROACTIVELY.**
{% endhint %}

This module is required to query a user's groups. Put the following configuration in a file called `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
```

To send the changes to the server, run the command:

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

#### Generate the database for your domain

Finally, we specify the database, which will use the previously created settings to serve all requests to the domain (value of `olcSuffix`). Update the DN of *Users* and *Groups* to match the domain settings. Put the settings in `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
```

To send the changes to the server, use the configured administrator account (`olcRootDN`) after the `-D`. The `ldapadd` utility will ask for the password of the previously defined administrator account.

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

### Troubleshooting Errors

Note that error messages returned by OpenLdap can be confusing. If you have problems with the installation, it is recommended to enable debug mode. Stop the slapd service and then restart the process directly with the debug flag `-d -1`:

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

If TLS is enabled, also include the string for the ldaps endpoint:

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

### Encrypting OpenLdap passwords

By default, OpenLdap stores passwords in plain text. To change this behavior, it is necessary to: [Set a global hash algorithm](#configurando-o-algoritmo-hash) for passwords and [enable the password policy](#criando-uma-politica-de-senha-padrao) to automatically encrypt any plain text password.

#### Configuring the Hash Algorithm

We will use the SHA-512 algorithm with 50000 rounds and a 16-byte salt. Create a file called `hash_algorithm.ldif`

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

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

To send the settings to the server:

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

#### Import the Password Policy Schema

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

#### Load the Password Policy module

Create a file called `password_policy_config.ldif` containing:

```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
```

Then send the changes with:

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

If you encounter an error indicating that pwdAttribute does not exist, this means the password policy schema was not imported.

#### Creating a Default Password Policy

Create a file called `password_policy.ldif` containing:

```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
```

Then send the changes with the command below, replacing the `olcRootDN`:

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

### Improving Security

#### Disabling Anonymous Binding

Create a file `disable_anon_binding.ldif` containing:

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

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

Then send the changes:

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

To test if the changes worked, run the following anonymous search:

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

#### Disabling Read Permission for User Passwords

Finally, any user can obtain another user’s password. Even if passwords are encrypted, this should be avoided. Especially if it is decided to keep passwords in plain text. So, create a file called `disabled_password_read.ldif`.

{% hint style="warning" %}
**MAKE SURE THERE IS NO LINE BREAK FOR 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
```

Send the changes:

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

If you run a bound search with any user that is not the olcRootDN, the only password returned will be that user’s own password.

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

### Enabling LDAPS

Before continuing, make sure your OpenLdap instance is working and that it has two organizational units: one for users and one for groups. You can do this using Apache Directory Studio to connect to the server using the ldap connection URL, for example: <ldap://192.168.0.100:389>, and with your configured administrator account (**olcRootDN**).

To enable LDAPS, a valid certificate signed by a trusted authority is required. Alternatively, we provide a guide on how to set up your own certificate authority and how to use it to sign your server certificates.

#### Create your CA

If you already have a valid certificate, you can skip this step.

On CentOS, you will find the file `openssl.cnf`, which contains the main configuration for your CA, in the directory `/etc/pki/tls`. However, our CA will be placed in `/etc/pki/CA`.

First, create the file `index.txt` and the serial files, which will contain information about signed certificates and the certificate serial number to be used, respectively.

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

Next, add the following policies to `/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
```

Now, change to the CA directory:

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

We will generate the CA certificate, valid for 10 years, with the following command. The utility will ask you to set the private key password and information about the certificate subject (the CA in this case). Note this password, it will be required to sign certificates.

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

Then, restrict access rights to the CA private key:

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

#### Create an LDAP Server Certificate

First, create a certificate signing request for the LDAP server:

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

Then, sign the `server.csr` using the CA private key:

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

Now, the `ldap_cert.pem` is the certificate for your server and your private key is in the file `ldap_key.pem`.

{% hint style="info" %}
the private key for the server is not encrypted (`-nodes` parameter). This is less secure, but **OpenLdap does not support encrypted keys**. So, it is essential to restrict all access to this file, as will be done in the following steps.
{% endhint %}

#### Configuring OpenLdap to use the certificate and key

First, copy the CA certificate to `/etc/openldap/cacerts`. This will make OpenLdap trust the certificate signed by your CA.

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

Next, install your ldap server certificate in `/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
```

Setting permission 400 for the server private key is **MANDATORY**.

Create a file called `enable_ldaps.ldif` with the following settings:

```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
```

Then, send the changes to the server and test the configuration files:

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

#### Enable the TLS Endpoint

In the file `/etc/sysconfig/slapd`add `ldaps:///` to the line that starts with `SLAPD_URLS=`. After that, the line should be similar to:

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

#### Force TLS

Create a file called `force_tls.ldif` with the following content:

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

Then, submit the changes to the server:

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

Now test the TLS requirement by running the following search. It should be denied due to the TLS requirement:

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

{% hint style="warning" %}
FROM NOW ON, ANY CALL TO `ldapi:///` THAT REQUIRES *olcRootDN* (i.e. those that create entries in the directory tree) MUST BE MADE ON `ldaps:///`. CALLS THAT CAN USE `-Y EXTERNAL` (i.e., that modify `cn=config`) CAN STILL USE `ldapi:///`.
{% endhint %}

#### Client-side TLS Configuration

To allow utilities such as `ldapsearch` to connect via TLS, add `TLS_REQCERT allow` address to `/etc/openldap/ldap.conf`:

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

### Create a Bind User for GBDS Ranger

GBDS and Ranger will require the user to bind to the LDAP server to perform queries and authentications. The only privilege this user needs is to read the directory tree.

{% hint style="warning" %}
Do not use olcRootDN as the bind user.
{% endhint %}

Create a file called `bind_user.ldif` with the following content. **Replace** the `dn:` for one that matches your installation. Additionally, set the bind user's password. If you enable password encryption, write the password in clear text. Otherwise, use slappasswd to produce a hash for the password and write the hash in the `.ldif` (Similar to how the password for **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>
```

Submit the changes with:

```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
```

To test if the user was created correctly, run the following search authenticating with the bind user `credentials:his`

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

### LDAP API

The LDAP API is an API provided by Griaule to assist with user and group management. You can authenticate, create, delete or modify user data and list user and group data through the API.

{% hint style="info" %}
If the API files were not provided, contact the Griaule Support Team.
{% endhint %}

The full API can be accessed at [LDAP API](https://app.gitbook.com/s/MqtschPie46KAAzuKKeD/ldap).

{% hint style="warning" %}
The API works with SSL security and requires a truststore and keystore. For more information on creating these, see the section [Configuring GBDS Security](#configurando-a-segurança-do-gbds).
{% endhint %}

#### Configuring the API

To properly install and configure the API, follow the steps:

1. Extract the provided package.
2. Under `/etc/griaule` create the directory `ldap`.
3. Move the directory `conf` from the provided package to the directory `/etc/griaule/ldap`.
4. Move the `config.properties` to the directory `/etc/griaule/ldap`.
5. Open the file `config.properties` and adjust the configuration parameters according to your environment.
6. Under `/var/lib/griaule` create the directory `ldap`.
7. Move the application `bs-ldap-api.jar` and the script `kill-api.sh` and `start-api.sh` to the new directory.
8. Run the start script.

#### Creating New Users and Groups

To create a new user, call [Create User](https://gitbook.griaule.com/apis/ldap/create#post-ldap-user). The API will create the user, the password and the groups to which the user belongs.

If modifications to an existing user are required, call [Modify User Data](https://gitbook.griaule.com/apis/ldap/user#put-ldap-user-user).

To retrieve user data, call [Get User Data](https://gitbook.griaule.com/apis/ldap/user#get-ldap-user-user).

To add, modify or delete groups, access `/etc/griaule/ldap/conf/group-list.json` and modify the file as desired. You can also view all groups by calling [List Groups](https://gitbook.griaule.com/apis/ldap/list#get-ldap-user-groups).

## Installing Ranger

After OpenLDAP or Active Directory are configured, you can proceed to install Ranger.

### Prerequisites

#### Installing ambari-infra

Go to Ambari and install the Ambari-infra service. This will provide a Solr instance to store audited data for Ranger.

#### Install and Configure the MySQL Instance

1. Install a MySQL instance
2. Create the rangerdba user and grant the necessary privileges

   ```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 that Rangerdba$1 is the password for the rangerdba user. Replace it with the desired password.
3. Test if the rangerdba user was created successfully: `mysql -u rangerdba -p`
4. Install the MySQL connector: `yum install mysql-connector-java*`
5. Register the connector with Ambari by running the following commands on the host with Ambari server installed: `ambari-server setup --jdbc-db=mysql --jdbc-driver=/usr/share/java/mysql-connector-java.jar`

### Installing the Ranger Service

Go to Ambari and add the Ranger service. Visit each of the following configuration tabs before finalizing the installation.

#### Ranger Admin

1. Leave the Ranger DB username as `rangeradmin`. Put whatever password you want, but save it for later.
2. Make sure the options `Setup Database` and `Database User` are checked as `Yes`
3. For the DBA username, use the user account created in the previous steps.

#### Ranger User Information

This service will import users and groups into the Ranger database.

{% hint style="info" %}
Below, we give **SUGGESTIONS** for values in several required configuration options. You should ensure they match your LDAP deployment.
{% endhint %}

1. Change the *Sync Source* to the `Ldap/AD`
2. On the *Common Config*:
   1. **LDAP/AD URL**: If the URL configured here is for LDAPS, the LDAPS certificate will need to be imported into the usersync truststore as described in the section [Importing the Ldaps Certificate](#importar-o-certificado-ldaps)
   2. **Bind User**: Fill in the bind user DN and password. The user only needs read privilege for the Users and Groups repository.
3. On the *User Configs*:
   1. **Username Attribute**: attributes that store the userName for login. For AD, **usually** `sAMAccountName` and for OpenLDAP, `uid`.
   2. **User Search Base**: DN for the node that contains the user that needs to be synchronized (AD User).
4. On the *Group Configs*:
   1. **Group member Attribute**: Group entity attribute that stores which user belongs to which group, in addition to information about the user-group membership. It is **usually** `member`
   2. **Group Name Attribute**: Group attribute that contains the group's name. **Usually** `cn`
   3. **Group Object Class**: Group entity class. For AD, it is **usually** `group`, for OpenLDAP it is **usually** `groupOfNames`
   4. **Group Search Base**: with the node that contains the groups that need to be synchronized

#### Ranger Audit

1. Check the option `Audit to Solr`
2. Check the option `Solr Cloud`

### Installation Check

#### User Synchronization

Go to the Ranger website at `http://<host>:6080`, log in and go to *Settings*, and then, *Users/Groups*. All users and groups from the *User/Group Search Base* should be present. If not, a user sync problem occurred. Check the log at `/var/log/ranger/usersync/usersync.log` to identify the error.

#### Solr Audit

Go to the ambari-infra UI and check for the existence of the collection `ranger_audits`

### Enabling LDAP Integration with TLS

To enable Ranger to use LDAPS instead of LDAP, two changes need to be made. First, we need to update the LDAP connection URL to the TLS-protected URL. Second, we need to import the LDAPS certificate.

#### Changing the LDAP Connection URL

Go, in Ambari, to *Ranger*, *Configs*, *Ranger User Info*, *Common Configs*. Change the LDAP/AD URL to `ldaps://<hostname>:636`

#### Importing the Ldaps Certificate

If your LDAP repository is using TLS, you need to import its certificate into the *UserSync truststore* of ranger.

To obtain the location of the *truststore*, go to Ambari, *Ranger*, *Configs*, *Advanced*, *Advanced ranger-ugsync-site*, `ranger.usersync.truststore.file`. Then, use Java keytool to import the Ldaps certificate into the *truststore*. If the *truststore* already exists, a password will be required. If not, note the password used. You will need it later.

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

Next, fix the permission and owner of the *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
```

If the *truststore* is new, go to Ambari, *Ranger*, *Configs*, *Advanced*, *Advanced ranger-ugsync-site* and set the properties:

1. **ranger.usersync.truststore.file**: with the absolute path to the *truststore*
2. **ranger.usersync.truststore.password**: password for the *truststore*

#### Troubleshooting Errors

If it is not possible to create the SSLContext for communication with the policy manager, there is a problem with the usersync credentials and keys. The only way to solve this problem is to delete the *truststore* `/usr/hdp/current/ranger-usersync/conf/mytrustore.jks`, recreate it with the Ldaps certificate and update the password configuration in Ambari, *Ranger*, *Configs*, *Advanced ranger-usersync-site*

## Configuring GBDS Security

Once Ranger, Solr and the LDAP server are installed and configured, we can proceed to GBDS configurations.

### Creating the GBDS Keystore

The keystore will be used to store bind user passwords and signing keys for the JWT tokens generated by the API.

Run the script `/var/lib/griaule/gbsapi/scripts/create_keystore.py` passing the path to the new keystore and the path to create the password file. The script will ask for the bind user's password to be saved. Then, the script will create the keystore with the bind user's password and a random signing key. The keystore will be protected by a randomly generated password, which will be saved in the specified password file. Finally, the keystore and password file will have their permissions changed to read-only.

```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" %}
The password file contains passwords in plain text. Therefore, it is essential that this be kept in a secure location with access allowed only to the user *griaule*.
{% endhint %}

### Creating *trustore* for LDAPS

If you intend to connect to your LDAP server using SSL, you need to import the server's certificate into a *truststore* and configure GBDS to use it.

Assuming the server certificate is named `server_cert.pem`, run the following command and use a strong password for the *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
```

Besides creating the *truststore*, this command will restrict access to the griaule user. Then, save the *truststore* password of the

```sh
in the password file.
```

### 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

Edit the file `/etc/griaule/conf/gbscluster.properties` Updating the Configuration File

1. **gbscluster.api.security.enabled**and modify the following properties: *true* : set to
2. **gbscluster.api.security.keystore**to enable security.`/etc/griaule/conf/gbsapi/keystore.jks`)
3. **gbscluster.api.security.truststore**: path to the keystore you created ( *truststore* : path to the`/etc/griaule/conf/gbsapi/truststore`)
4. **gbscluster.api.security.passwords**you created (`: path to the password file (`)
5. **gbscluster.api.security.ldap.url**etc/griaule/conf/gbsapi/.passwords `: LDAP server URL, example:`ldap\://\<host>:389 `. If you enabled Ldaps, this should be`
6. **gbscluster.api.security.ldap.userSearchBase**ldaps\://\<host>:636 `: The DN of the node in the tree that holds the users who will be enabled for authentication in GBDS. In your OpenLDAP installation guide, the DN should be:`

   > **ou=Users,dc=oldap,dc=pd,dc=griaule**
7. **gbscluster.api.security.ldap.userSearchAttribute**IT MUST BE THE SAME DN CONFIGURED IN RANGER `: User entity attribute that contains the`userName

   > **, which will be used during authentication.**
8. **gbscluster.api.security.ldap.userGroupMembershipAttribute**IT MUST BE THE SAME AS CONFIGURED IN RANGER

   > **, which will be used during authentication.**
9. **gbscluster.api.security.ldap.bindUserDN**: User entity attribute that contains the DNs of the groups it belongs to. Usually memberOf.
10. **gbscluster.api.security.token.ttlInMilliseconds**: Bind user DN. Use the same one configured for Ranger.

## : Lifetime, in milliseconds, for the JWT token generated by the API. Valid values are between 30 minutes and 3 hours. We recommend 1 hour.

Installing the Ranger Authorization Service

To install and run the Ranger authorization service, you must have created a GBDS user and an ADMIN user. `To create the administrator user, open the file` in the folder `administrator_group.ldif` /etc/openldap

```default
and add the following to the file:
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 `Then, in the file`gbds\_user.ldif

```default
, create the GBDS user.
dn: cn=administrator,ou=Groups,dc=oldap,dc=pd,dc=griaule
dn: cn=gbds_user,ou=Groups,dc=oldap,dc=pd,dc=griaule
cn: administrator
description: IT Security Group
# Add the group members all of which are assumed to exist under people
```

cn: gbds\_user

```sh
Apply the changes by restarting Ranger via the Ambari GUI.
sudo ldapadd -D "cn=ldapadm,dc=oldap,dc=pd,dc=griaule" -W -H ldapi:/// -f /etc/openldap/administrator_group.ldif
```

{% hint style="info" %}
sudo ldapadd -D "cn=ldapadm,dc=oldap,dc=pd,dc=griaule" -W -H ldapi:/// -f /etc/openldap/gbds\_user.ldif `ldapi:///` If TLS is enabled, remember to change `ldaps:///`.
{% endhint %}

to

```sh
When the changes are applied, run the Ranger Authorization Policy.
```

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> `To finalize the process, update the Ranger XML Files. Go to` /etc/griaule/conf/gbsapi/ `and in the file`ranger-gbds-audit.xml

```xml
, modify as follows:
<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> `Do the same for`

```xml
ranger-gbds-security.xml
<name>ranger.plugin.gbds.policy.rest.url</name>
```

## \<value><http://localhost:6080\\></value>

Configuring PHP LDAP Admin

PHP LDAP Admin is a tool to manage OPENLDAP via GUI; it is an alternative to using the CLI. The user can add/modify/delete users, groups, roles, etc. via the GUI. Note that this is not required for LDAP to function.

Under `First, install PHPLDAPAdmin dependencies.`/etc/httpd/conf.d `then update the file` with

```properties
phpldapadmin.conf
# Require local
```

Require all granted `And also update the file` in the folder `config.php` with

```php
/etc/phpldapadmin
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');

```sh
Run the following command to start and enable the HTTPD services
```

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

```sh
After enabling HTTPD, it is necessary to allow the possible updates. If the firewall is enabled, run
firewall-cmd --permanent --zone=public --add-service=http
```

firewall-cmd --reload

```sh
And if SELinux is enabled, run
```

setsebool -P httpd\_can\_connect\_ldap on
