ExceptionFactory

Producing content that a reasonable developer might want to read

Single User Access and HTTPS in Apache NiFi

NiFi Security

2021-07-21 • 8 minute read • David Handermann

Background

The world was a different place when Clifford Stoll published The Cuckoo’s Egg in 1989. What started as a mundane task tracing down an accounting problem resulted in uncovering vulnerabilities across multiple government computer systems. Persistence and attention to detail eventually led Stoll to discover the espionage activities of a hacker working for the KGB. The teleprinters and 1200 baud connections of the 1980s may sound like ancient history, but the vulnerabilities that allowed the hacker to gain unauthorized access still plague modern systems. Default configuration settings make it easy to get started, but also open the door to potential problems.

Introduction

Apache NiFi has supported advanced security features from its inception, but version 1.14.0 brings several important changes to the default configuration. NiFi now enables single user authentication and HTTPS access without requiring any custom configuration. Documentation related to securing NiFi still applies, and should be followed for production deployments. NiFi 1.13.0 changed the default listening address to 127.0.0.1, and version 1.14.0 retains the same configuration. The new default settings have several inherent limitations, but for those interested in rapid prototyping or feature demonstrations, version 1.14.0 provides a more secure foundation for getting started.

Unencrypted and Unauthenticated

Prior to version 1.14.0, NiFi properties specified TCP port 8080 as the default for HTTP access. NiFi did not specify a Login Identity Provider, and disabled authentication when receiving requests over unencrypted HTTP. This approach provided easy access for developers and new users, but offered no protection around the many capabilities that NiFi provides.

Despite extensive product documentation, default settings made it too easy to run NiFi with a dangerous configuration. The ability to download an archive and run a command is great for usability, but not so great for security. Powerful capabilities need sufficient security. Instead of requiring manual configuration to secure the system, NiFi 1.14.0 bridges the gap and continues to support a wide array of additional configuration options.

Single User Authentication

Single user authentication is a new capability intended to provide exactly what it describes: authentication for a single user. Leveraging existing Login Identity Provider and Authorizer interfaces, single user authentication enforces access for one user. This feature supports a minimal amount of configuration and attempts to balance the concerns of usability and security.

Generated Credentials

Without any configuration, the Single User Login Identity Provider will generate both a random username and a random password. Although many products use a default username with a random password, NiFi uses a random string for both attributes. NiFi uses the Java UUID class to generate a random string of 36 characters for the username. For the password, NiFi uses the Java SecureRandom class to generate 24 bytes, which NiFi translates to a string of 32 characters using Base64 encoding. After generating a username and password, NiFi writes the generated values to the log and stores the values in the Login Identity Provider configuration. NiFi logs the random username and password values on separate lines as follows:

Generated Username [USERNAME]
Generated Password [PASSWORD]

Although these generated values provide a degree of protection against external access, they are difficult to remember and use for recurring access. Password managers provide one option for handling lengthy credentials, but usability concerns prompted the addition of a simple command to specify a custom username and password.

Custom Credentials

When running NiFi on an operating system that supports standard shell commands, the NiFi script can be used to set credentials for single user authentication. The script command updates the Login Identity Provider configuration, requiring a restart to apply the changes. The command requires a username with a minimum length of four characters and a password with a minimum length of 12 characters. Substituting the USERNAME and PASSWORD values, the following command can be executed from the NiFi home directory:

./bin/nifi.sh set-single-user-credentials USERNAME PASSWORD

The set-single-user-credentials command overwrites existing settings without prompting for a confirmation. Shell command history should be cleared after running this command.

Custom Credentials for Containers

In addition to the script command, NiFi supports using environment variables to specify the username and password when running NiFi on a containerized platform such as Docker or Kubernetes. With the following environment variables specified, NiFi will configure single user credentials as part of the startup process:

Using environment variables for these attributes makes them visible to anyone who can inspect the container configuration. Running the set-single-user-credentials command within the container and restarting is also option for setting custom credentials. In absence of custom configuration, NiFi will generate a random username and password as described earlier.

Storing Credentials

Rather than introducing an external storage solution, NiFi uses the Login Identity Providers configuration file to store the username and password. This approach allows NiFi to load both the provider definition and the credentials from a common location.

The default login-identity-providers.xml contains empty elements for the username and password properties.

<provider>
  <identifier>single-user-provider</identifier>
  <class>org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider</class>
  <property name="Username" />
  <property name="Password" />
</provider>

An empty password triggers the generation of both a random username and password. NiFi stores the username as a string, and uses bcrypt hashing to store the password. The bcrypt hash uses the February 2014 2B version for hashing with a cost factor of 12, as indicated in the hash. The password encoder relies on the excellent bcrypt library from Patrick Favre-Bulle to generate the hash. After credential generation, login-identity-providers.xml contains updated elements for the username and password.

<provider>
  <identifier>single-user-provider</identifier>
  <class>org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider</class>
  <property name="Username">exceptionfactory</property>
  <property name="Password">$2b$12$hcQlyAjTHng1gL73rDlS2.21Dtumrl7lXZTv2cnh2oHEcTEV3Yp46</property>
</provider>

Single User Authorization

Single user authentication includes a companion Single User Authorizer that allows the authenticated user to perform all operations. The default authorizers.xml configuration contains the Single User Authorizer definition.

<authorizer>
  <identifier>single-user-authorizer</identifier>
  <class>org.apache.nifi.authorization.single.user.SingleUserAuthorizer</class>
</authorizer>

The default nifi.properties references this authorizer in the following property:

nifi.security.user.authorizer=single-user-authorizer

The Single User Authorizer is not intended for use with any other authentication configuration. For this reason, the authorizer includes validation to ensure that NiFi has configured and initialized the Single User Login Identity Provider. Existing capabilities for authorizing multiple users must be configured with other Login Identity Providers.

When configuring a different authorizer, such as the Managed Authorizer for multiple tenants, the Single User Authorizer definition should be commented out or removed from login-identity-providers.xml.

HTTPS Access

NiFi has supported access over HTTPS from the beginning, but version 1.14.0 lowers the barrier to entry by providing automatic generation of a key pair and certificate for the server.

Existing guidance on obtaining and configuring a certificate from a trusted authority still applies, but automatic generation supports HTTPS access regardless of network connectivity. Automatic certificate generation is not intended for production deployments. With the change from HTTP to HTTPS in the default configuration, NiFi now binds to the loopback address on TCP port 8443.

Self-Signed Certificates

All web browsers display some type of warning message when connecting to servers using self-signed certificates. Accessing NiFi is no exception. Self-signed certificates do not impact the type of encryption, but the use of self-signed certificates indicates that the web browser cannot verify the identity of the remote server.

Most web browsers provide the ability to view the certificate of the remote server prior to connecting. This provides the opportunity to verify the certificate fingerprint against the fingerprint of the certificate that NiFi generated. For those interested in making the comparison, NiFi logs the certificate fingerprint as a hexadecimal-encoded string of the SHA-256 hash in nifi-bootstrap.log.

Generated Self-Signed Certificate SHA-256: HEXADECIMALS

Certificate Expiration

The self-signed certificate generated at startup has a hard-coded expiration of 60 days. This intent of the short certificate lifespan is to encourage configuration of a certificate signed by a trusted authority. NiFi logs the expiration of the generated certificate in nifi-bootstrap.log.

Generating Self-Signed Certificate: Expires 2021-12-31

KeyStore and TrustStore Generation

As part of automatic key pair and certificate generation, NiFi creates a KeyStore and TrustStore for storing the information. NiFi uses the standard KeyStore and TrustStore properties to determine the file locations and store the passwords necessary for reading the files.

The default nifi.properties configuration uses several properties to specify the file location and type for the KeyStore and TrustStore.

nifi.security.keystore=./conf/keystore.p12
nifi.security.keystoreType=PKCS12
nifi.security.truststore=./conf/truststore.p12
nifi.security.truststoreType=PKCS12

NiFi defaults to PKCS12 as the format for both KeyStore and TrustStore files. The PKCS12 format provides better compatibility with other tools than JKS, and is also the default Java KeyStore format starting in Java 9.

The default password properties associated with the KeyStore and TrustStore are blank, and the absence of the files together with blank passwords triggers NiFi to generate a new KeyStore and TrustStore. After generating new files, NiFi updates the passwords with random values.

nifi.security.keystorePasswd=RANDOM
nifi.security.keyPasswd=RANDOM
nifi.security.truststorePasswd=RANDOM

Each random password consists of 32 characters produced through hexadecimal encoding of 16 random bytes generated from the Java SecureRandom class.

Conclusion

Apache NiFi 1.14.0 builds on a foundation of configurable security and provides a better starting point for simple deployments. Single user authentication and automatic certificate generation for HTTPS access do not provide everything necessary for a production system, but these features close several gaps in the default configuration. Understanding the capabilities and limitations of these features can be helpful when considering both new installations and planned upgrades. Better default settings may not stop a determined intruder, but they avoid leaving the door open.