---
title: "Setup LDAP for Apache Nifi"
url: "https://vanducng.dev/2019/11/20/Setup-LDAP-for-Apache-Nifi/"
date: "2019-11-20"
categories: ["Data"]
tags: ["airflow","security"]
---

# Setup LDAP for Apache Nifi

<p align="center"> ![Insecured Nifi](https://vanducng.dev/media/images/unsecured_nifi.png) </p>

Default Apache Nifi installation comes without security layer which exposes the development UI. As a result, users can freely access the Nifi project development with knowledge about the hostname and binding Port. You can see two potential security risks:

* **Flow controller attack** : full policies to modify the processor on Flow Controller.
* **API attack**: external invoked requests to start/stop/delete Nifi components.

## Implement strategy
To protect the unexpected security issues related, this post will help to list out steps by steps to setup security layer in the default Apache Nifi installation.  The LDAP User Authentication method is used because of its easy to manage and setup while maintains secured manner. Details on can be found [HERE](https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#ldap_login_identity_provider) from the official website.

There are three main components added to the previously diagram, including LDAP server, Authentication and Authentization:

* **LDAP server**: manage the users’ access to Nifi server. This server can be deployed within same or seperate server with Nifi. In this post, the OpenLDAP library is used as its popularity.
* **Authentication**: enable authentication feature to perform a handshake with LDAP server to recognize who is logging on the server.
* **Authorization**: distinguish the which policies are applied for current login account.

To enable these 3 components, it required to setup an additional LDAP server apart from Nifi service; and perform configuration for number of config files such as nifi.properties, login-identity-providers.xml, authorizers.xml, etc. The next 3 sections will describe the implementation details for these 3 componenents.

![Secured Nifi](https://vanducng.dev/media/images/secured_nifi.png)

## LDAP Server

Simply run an OpenLDAP docker as below:

```bash
docker run --name vanducng-openldap --env LDAP_ORGANISATION="myorg" --env LDAP_DOMAIN="vanducng.dev" --env 
LDAP_ADMIN_PASSWORD="SuperSecret" -p 389:389 -p 636:636 -d osixia/openldap
```

We target run on domain vanducng.dev with initial admin password of “SuperSecret” which later on can be change via ADS. Further configurations can be found from [here](https://github.com/osixia/docker-openldap).

## Authentication
Then LDAP server is now accessible using docker machine IP. It can be checked by `iptables -L` command:
However, to enable a handshake with LDAP server, Nifi has to be configured to enable HTTPS/SSL first as stated in the [official document](https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#user_authentication).

### Use toolkit to generate config files
Start following commands to download the nifi toolkit to generate the List of configuration files are shown as below including keystore.jks, nifi-cert.pem, nifi-key.key, nifi.properties, truststore.jks.

```bash
wget http://www-eu.apache.org/dist/nifi/1.10.0/nifi-toolkit-1.10.0-bin.tar.gz
tar xvf nifi-toolkit-1.10.0-bin.tar.gz
cd nifi-toolkit-1.10.0/bin
./tls-toolkit.sh standalone -n 'vanducng.dev'

mv nifi-* vanducng.dev/
```

Move these files to conf folder under nifi location:
```bash
mv vanducng.dev/* /nifi/conf/
```

### Edit nifi.properties
Open the file with preferred text editor:
```bash
nano /nifi/conf/nifi.properties
```

In web properties section, apply the https hostname and specific port as following. The hostname must be same as domain name for public access, else the webserver will return a header error. In this example, I was using Amazon EC2 as remote server.

```perl nifi.properties
# web properties #
nifi.web.war.directory=./lib
nifi.web.http.host=
nifi.web.http.port=
nifi.web.http.network.interface.default=
nifi.web.https.host=ec2-xxx-xxx-xxx-xxx.ap-southeast-1.compute.amazonaws.com
nifi.web.https.port=9443
nifi.web.https.network.interface.default=
nifi.web.jetty.working.directory=./work/jetty
nifi.web.jetty.threads=200
nifi.web.max.header.size=16 KB
nifi.web.proxy.context.path=
nifi.web.proxy.host=
```

Ensure the ldap-provider is configured in `nifi.security.user.login.identity.provider` as well.
```perl nifi.properties
# security properties #
nifi.sensitive.props.key=
nifi.sensitive.props.key.protected=
nifi.sensitive.props.algorithm=PBEWITHMD5AND256BITAES-CBC-OPENSSL
nifi.sensitive.props.provider=BC
nifi.sensitive.props.additional.keys=

nifi.security.keystore=./conf/keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=OYW1Iuvk1Wi1Oraccw7/wTdHn1GzeWI5btS+7vPB8tc
nifi.security.keyPasswd=OYW1Iuvk1Wi1Oraccw7/wTdHn1GzeWI5btS+7vPB8tc
nifi.security.truststore=./conf/truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=uTxsOQauQ3a7PopBfVjHGn7+UqWXG2Gn8j4sDax6ykA
nifi.security.user.authorizer=managed-authorizer
nifi.security.user.login.identity.provider=ldap-provider
nifi.security.ocsp.responder.url=
nifi.security.ocsp.responder.certificate=
```

### Map hostname with private IP address
Open hosts file:
```bash
nano /etc/hosts
```

Map the private IP address of the EC2 instance with the hostname defined in nifi.properties config file.
```bash
172.31.23.12 ec2-xxx-xxx-xxx-xxx.ap-southeast-1.compute.amazonaws.com
```

### Edit login-identity-providers.xml
Similar to nifi.properties, open login-identity-providers.xml with preferred text editor, then uncomment ldap-provider xml block and configure the LDAP information that has been setup in previous step.
```xml login-identity-providers.xml
<provider>
    <identifier>ldap-provider</identifier>
    <class>org.apache.nifi.ldap.LdapProvider</class>
    <property name="Authentication Strategy">SIMPLE</property>

    <property name="Manager DN">cn=admin,dc=vanducng,dc=dev</property>
    <property name="Manager Password">SuperSecret</property>

    <property name="TLS - Keystore"></property>
    <property name="TLS - Keystore Password"></property>
    <property name="TLS - Keystore Type"></property>
    <property name="TLS - Truststore"></property>
    <property name="TLS - Truststore Password"></property>
    <property name="TLS - Truststore Type"></property>
    <property name="TLS - Client Auth"></property>
    <property name="TLS - Protocol"></property>
    <property name="TLS - Shutdown Gracefully"></property>

    <property name="Referral Strategy">FOLLOW</property>
    <property name="Connect Timeout">10 secs</property>
    <property name="Read Timeout">10 secs</property>

    <property name="Url">ldap://ip-172-17-0-2.ap-southeast-1.compute.internal:389</property>
    <property name="User Search Base">dc=vanducng,dc=dev</property>
    <property name="User Search Filter">cn={0}</property>

    <property name="Identity Strategy">USE_DN</property>
    <property name="Authentication Expiration">12 hours</property>
</provider>
```

After finish this step, restart Nifi to apply the new configuration.
```bash
/nifi/bin/nifi.sh restart
```
Under the hood, Jetty server started apply the additional security settings and host the web via defined domain name. It can be check by parsing the nifi-app.log as below.

```bash
cat tail /nifi/logs/nifi-app.log 
```

## Authorization
With authentication setup, initial admin user from LDAP server that has been defined in authentication step can login to the Nifi webserver, no tasks can be performed because of no policies applied as below image:

![](https://vanducng.dev/media/images/login_pemission_denied.png)

To get into development stage and assign policies for new users, it required to setup initial admin identity and logged-in admin to perform policies assignment since then.

### Setup initial admin identity
To pass authorities for admin user, edit the `authorizer.xml` in config folder by enabling authorizer with file-provider as below. 

```xml authorizer.xml
<authorizer>
    <identifier>file-provider</identifier>
    <class>org.apache.nifi.authorization.FileAuthorizer</class>
    <property name="Authorizations File">./conf/authorizations.xml</property>
    <property name="Users File">./conf/users.xml</property>
    <property name="Initial Admin Identity">cn=admin,dc=vanducng,dc=dev</property>
    <property name="Legacy Authorized Users File"></property>

    <property name="Node Identity 1">CN=localhost, OU=NIFI</property>
</authorizer>
```

### Assign policies for registered users
Restart Nifi service, them admin user has full access and able to assign policies for LDAP user. 

![](https://vanducng.dev/media/images/assign_policies_in_nifi.png)


## References
1. [https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html](https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html)
2. [https://nifi.apache.org/docs/nifi-docs/rest-api/index.html](https://nifi.apache.org/docs/nifi-docs/rest-api/index.html)
3. [https://docs.oracle.com/cd/B10501_01/network.920/a96579/comtools.htm](https://docs.oracle.com/cd/B10501_01/network.920/a96579/comtools.htm)
4. [https://mintopsblog.com/2017/11/01/apache-nifi-configuration/](https://mintopsblog.com/2017/11/01/apache-nifi-configuration/)
5. [http://ijokarumawak.github.io/nifi/2016/11/15/nifi-auth](http://ijokarumawak.github.io/nifi/2016/11/15/nifi-auth)
