NIFI-8516 Enabled HTTPS and Single User Authentication in default configuration

- Set default HTTPS Port to 9443
- Set default authorizer to single-user-authorizer
- Set default login-identity-provider to single-user-provider
- Updated README.md with authentication instructions using generated credentials
- Updated default URL and port information in Administration and User Guides
- Updated Getting Started Guide with authentication and URL changes
- Updated Docker images to set HTTPS as default configuration
- Updated default HTTPS port to 8443
- Set Cluster Protocol secure property in Docker start scripts
- Added set-single-user-credentials command
- Refactored shared classes to nifi-single-user-utils
- Updated Getting Started documentation and logging
- Updated documentation and TLS Toolkit default ports
- Updated Toolkit Guide and Administration Guide
- Updated README.md with HTTPS links
This commit is contained in:
exceptionfactory 2021-05-11 12:18:08 -05:00 committed by Mark Payne
parent d7a8d275c9
commit db40989b48
45 changed files with 679 additions and 145 deletions

159
README.md
View File

@ -66,67 +66,112 @@ Apache NiFi was made for dataflow. It supports highly configurable directed grap
## Getting Started
- Read through the [quickstart guide for development](http://nifi.apache.org/quickstart.html).
It will include information on getting a local copy of the source, give pointers on issue
tracking, and provide some warnings about common problems with development environments.
- For a more comprehensive guide to development and information about contributing to the project
read through the [NiFi Developer's Guide](http://nifi.apache.org/developer-guide.html).
Read through the [quickstart guide for development](https://nifi.apache.org/quickstart.html).
It will include information on getting a local copy of the source, give pointers on issue
tracking, and provide some warnings about common problems with development environments.
To build:
- Execute `mvn clean install` or for parallel build execute `mvn -T 2.0C clean install`. On a
modest development laptop that is a couple of years old, the latter build takes a bit under ten
minutes. After a large amount of output you should eventually see a success message.
For a more comprehensive guide to development and information about contributing to the project
read through the [NiFi Developer's Guide](https://nifi.apache.org/developer-guide.html).
laptop:nifi myuser$ mvn -T 2.0C clean install
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 115 modules...
...tens of thousands of lines elided...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 09:24 min (Wall Clock)
[INFO] Finished at: 2015-04-30T00:30:36-05:00
[INFO] Final Memory: 173M/1359M
[INFO] ------------------------------------------------------------------------
- Execute `mvn clean install -DskipTests` to compile tests, but skip running them.
### Building
To deploy:
- Change directory to 'nifi-assembly'. In the target directory, there should be a build of nifi.
Run `mvn clean install` or for parallel build execute `mvn -T 2.0C clean install`.
laptop:nifi myuser$ cd nifi-assembly
laptop:nifi-assembly myuser$ ls -lhd target/nifi*
drwxr-xr-x 3 myuser mygroup 102B Apr 30 00:29 target/nifi-1.0.0-SNAPSHOT-bin
-rw-r--r-- 1 myuser mygroup 144M Apr 30 00:30 target/nifi-1.0.0-SNAPSHOT-bin.tar.gz
-rw-r--r-- 1 myuser mygroup 144M Apr 30 00:30 target/nifi-1.0.0-SNAPSHOT-bin.zip
The parallel build should take around fifteen minutes on modern hardware.
- For testing ongoing development you could use the already unpacked build present in the directory
named "nifi-*version*-bin", where *version* is the current project version. To deploy in another
location make use of either the tarball or zipfile and unpack them wherever you like. The
distribution will be within a common parent directory named for the version.
laptop:nifi myuser$ mvn -T 2.0C clean install
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 115 modules...
...tens of thousands of lines elided...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 09:24 min (Wall Clock)
[INFO] Finished at: 2015-04-30T00:30:36-05:00
[INFO] Final Memory: 173M/1359M
[INFO] ------------------------------------------------------------------------
laptop:nifi-assembly myuser$ mkdir ~/example-nifi-deploy
laptop:nifi-assembly myuser$ tar xzf target/nifi-*-bin.tar.gz -C ~/example-nifi-deploy
laptop:nifi-assembly myuser$ ls -lh ~/example-nifi-deploy/
total 0
drwxr-xr-x 10 myuser mygroup 340B Apr 30 01:06 nifi-1.0.0-SNAPSHOT
Run `mvn clean install -DskipTests` to skip unit test execution.
To run NiFi:
- Change directory to the location where you installed NiFi and run it.
### Deploying
laptop:~ myuser$ cd ~/example-nifi-deploy/nifi-*
laptop:nifi-1.0.0-SNAPSHOT myuser$ ./bin/nifi.sh start
Issuing `bin/nifi.sh start` executes the `nifi.sh` script that starts NiFi in the background and then exits. If you want `nifi.sh` to wait for NiFi to finish scheduling all components before exiting, use the `--wait-for-init` flag with an optional timeout specified in seconds.
Change directories to `nifi-assembly`. The `target` directory contains binary archives.
laptop:nifi-1.0.0-SNAPSHOT myuser$ ./bin/nifi.sh start --wait-for-init 120
- Direct your browser to http://localhost:8080/nifi/ and you should see a screen like this screenshot:
![image of a NiFi dataflow canvas](nifi-docs/src/main/asciidoc/images/nifi_first_launch_screenshot.png?raw=true)
laptop:nifi myuser$ cd nifi-assembly
laptop:nifi-assembly myuser$ ls -lhd target/nifi*
drwxr-xr-x 3 myuser mygroup 102B Apr 30 00:29 target/nifi-1.0.0-SNAPSHOT-bin
-rw-r--r-- 1 myuser mygroup 144M Apr 30 00:30 target/nifi-1.0.0-SNAPSHOT-bin.tar.gz
-rw-r--r-- 1 myuser mygroup 144M Apr 30 00:30 target/nifi-1.0.0-SNAPSHOT-bin.zip
- For help building your first data flow see the [NiFi User Guide](http://nifi.apache.org/docs/nifi-docs/html/user-guide.html)
Copy the `nifi-VERSION-bin.tar.gz` or `nifi-VERSION-bin.zip` to a separate deployment directory.
Extracting the distribution will create a new directory named for the version.
- If you are testing ongoing development, you will likely want to stop your instance.
laptop:nifi-assembly myuser$ mkdir ~/example-nifi-deploy
laptop:nifi-assembly myuser$ tar xzf target/nifi-*-bin.tar.gz -C ~/example-nifi-deploy
laptop:nifi-assembly myuser$ ls -lh ~/example-nifi-deploy/
total 0
drwxr-xr-x 10 myuser mygroup 340B Apr 30 01:06 nifi-1.0.0-SNAPSHOT
laptop:~ myuser$ cd ~/example-nifi-deploy/nifi-*
laptop:nifi-1.0.0-SNAPSHOT myuser$ ./bin/nifi.sh stop
### Starting
Change directories to the deployment location and run the following command to start NiFi.
laptop:~ myuser$ cd ~/example-nifi-deploy/nifi-*
laptop:nifi-1.0.0-SNAPSHOT myuser$ ./bin/nifi.sh start
Running `bin/nifi.sh start` starts NiFi in the background and exits. Use `--wait-for-init` with an optional timeout in
seconds to wait for a complete startup before exiting.
laptop:nifi-1.0.0-SNAPSHOT myuser$ ./bin/nifi.sh start --wait-for-init 120
### Authenticating
The default configuration generates a random username and password on startup. NiFi writes the generated credentials
to the application log located in `logs/nifi-app.log` under the NiFi installation directory.
The following command can be used to find the generated credentials on operating systems with `grep` installed:
laptop:nifi-1.0.0-SNAPSHOT myuser$ grep Generated logs/nifi-app*log
NiFi logs the generated credentials as follows:
Generated Username [USERNAME]
Generated Password [PASSWORD]
The `USERNAME` will be a random UUID composed of 36 characters. The `PASSWORD` will be a random string composed of
32 characters. The generated credentials will be stored in `conf/login-identity-providers.xml` with the password stored
using bcrypt hashing. Record these credentials in a secure location for access to NiFi.
The random username and password can be replaced with custom credentials using the following command:
./bin/nifi.sh set-single-user-credentials <username> <password>
### Running
Open the following link in a web browser to access NiFi: https://localhost:8443/nifi
The web browser will display a warning message indicating a potential security risk due to the self-signed
certificate NiFi generated during initialization. Accepting the potential security risk and continuing to load
the interface is an option for initial development installations. Production deployments should provision a certificate
from a trusted certificate authority and update the NiFi keystore and truststore configuration.
Accessing NiFi after accepting the self-signed certificate will display the login screen.
![NiFi Login Screen](nifi-docs/src/main/asciidoc/images/nifi-login.png?raw=true)
Using the generated credentials, enter the generated username in the `User` field
and the generated password in the `Password` field, then press `LOG IN` to access the system.
![NiFi Flow Authenticated Screen](nifi-docs/src/main/asciidoc/images/nifi-flow-authenticated.png?raw=true)
### Configuring
The [NiFi User Guide](https://nifi.apache.org/docs/nifi-docs/html/user-guide.html) describes how to build a data flow.
### Stopping
Run the following command to stop NiFi:
laptop:~ myuser$ cd ~/example-nifi-deploy/nifi-*
laptop:nifi-1.0.0-SNAPSHOT myuser$ ./bin/nifi.sh stop
## MiNiFi subproject
@ -264,32 +309,32 @@ For a full list of the available DataSource factories, consult the `nifi-registr
## Getting Help
If you have questions, you can reach out to our mailing list: dev@nifi.apache.org
([archive](http://mail-archives.apache.org/mod_mbox/nifi-dev)). For more interactive discussions, community members can often be found in the following locations:
([archive](https://lists.apache.org/list.html?dev@nifi.apache.org)). For more interactive discussions, community members can often be found in the following locations:
- Apache NiFi Slack Workspace: https://apachenifi.slack.com/
New users can join the workspace using the following [invite link](https://s.apache.org/nifi-community-slack).
- IRC: #nifi on [irc.freenode.net](http://webchat.freenode.net/?channels=#nifi)
- IRC: #nifi on [irc.freenode.net](https://webchat.freenode.net/?channels=#nifi)
To submit a feature request or bug report, please file a Jira at [https://issues.apache.org/jira/projects/NIFI/issues](https://issues.apache.org/jira/projects/NIFI/issues). If this is a **security vulnerability report**, please email [security@nifi.apache.org](mailto:security@nifi.apache.org) directly and review the [Apache NiFi Security Vulnerability Disclosure](https://nifi.apache.org/security.html) and [Apache Software Foundation Security](https://www.apache.org/security/committers.html) processes first.
## Documentation
See http://nifi.apache.org/ for the latest NiFi documentation.
See https://nifi.apache.org/ for the latest NiFi documentation.
See https://nifi.apache.org/minifi and https://cwiki.apache.org/confluence/display/MINIFI for the latest MiNiFi-specific documentation.
## License
Except as otherwise noted this software is licensed under the
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
[Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@ -304,7 +349,7 @@ currently reside may have restrictions on the import, possession, use, and/or
re-export to another country, of encryption software. BEFORE using any
encryption software, please check your country's laws, regulations and
policies concerning the import, possession, or use, and re-export of encryption
software, to see if this is permitted. See <http://www.wassenaar.org/> for more
software, to see if this is permitted. See <https://www.wassenaar.org/> for more
information.
The U.S. Government Department of Commerce, Bureau of Industry and Security
@ -321,9 +366,9 @@ The following provides more details on the included cryptographic software:
Apache NiFi uses BouncyCastle, JCraft Inc., and the built-in
Java cryptography libraries for SSL, SSH, and the protection
of sensitive configuration parameters. See
http://bouncycastle.org/about.html
https://bouncycastle.org/about.html
http://www.jcraft.com/c-info.html
http://www.oracle.com/us/products/export/export-regulations-345813.html
https://www.oracle.com/corporate/security-practices/corporate/governance/global-trade-compliance.html
for more details on each of these libraries cryptography features.
[nifi]: https://nifi.apache.org/

View File

@ -286,6 +286,12 @@ language governing permissions and limitations under the License. -->
<version>1.14.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-single-user-iaa-providers-nar</artifactId>
<version>1.14.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-dbcp-service-nar</artifactId>

View File

@ -51,6 +51,12 @@ language governing permissions and limitations under the License. -->
<version>1.14.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-single-user-utils</artifactId>
<version>1.14.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>

View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-commons</artifactId>
<version>1.14.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-single-user-utils</artifactId>
<dependencies>
<dependency>
<groupId>at.favre.lib</groupId>
<artifactId>bcrypt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authentication.single.user;
import java.util.Objects;
/**
* Single User Credentials used for writing updated configuration
*/
public class SingleUserCredentials {
private final String username;
private final String password;
private final String providerClass;
public SingleUserCredentials(final String username, final String password, final String providerClass) {
this.username = Objects.requireNonNull(username, "Username required");
this.password = Objects.requireNonNull(password, "Password required");
this.providerClass = Objects.requireNonNull(providerClass, "Provider Class required");
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getProviderClass() {
return providerClass;
}
}

View File

@ -0,0 +1,96 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authentication.single.user.command;
import org.apache.nifi.authentication.single.user.SingleUserCredentials;
import org.apache.nifi.authentication.single.user.encoder.BCryptPasswordEncoder;
import org.apache.nifi.authentication.single.user.encoder.PasswordEncoder;
import org.apache.nifi.authentication.single.user.writer.LoginCredentialsWriter;
import org.apache.nifi.authentication.single.user.writer.StandardLoginCredentialsWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Properties;
/**
* Set Single User Credentials in Login Identity Providers configuration
*/
public class SetSingleUserCredentials {
protected static final String PROPERTIES_FILE_PATH = "nifi.properties.file.path";
protected static final String PROVIDERS_PROPERTY = "nifi.login.identity.provider.configuration.file";
private static final String PROVIDER_CLASS = "org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider";
private static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
private static final int MINIMUM_USERNAME_LENGTH = 4;
private static final int MINIMUM_PASSWORD_LENGTH = 12;
public static void main(final String[] arguments) {
if (arguments.length == 2) {
final String username = arguments[0];
final String password = arguments[1];
if (username.length() < MINIMUM_USERNAME_LENGTH) {
System.err.printf("ERROR: Username must be at least %d characters%n", MINIMUM_USERNAME_LENGTH);
} else if (password.length() < MINIMUM_PASSWORD_LENGTH) {
System.err.printf("ERROR: Password must be at least %d characters%n", MINIMUM_PASSWORD_LENGTH);
} else {
final String encodedPassword = PASSWORD_ENCODER.encode(password.toCharArray());
run(username, encodedPassword);
}
} else {
System.err.printf("Unexpected number of arguments [%d]%n", arguments.length);
System.err.printf("Usage: %s <username> <password>%n", SetSingleUserCredentials.class.getSimpleName());
}
}
private static void run(final String username, final String encodedPassword) {
final String propertiesFilePath = System.getProperty(PROPERTIES_FILE_PATH);
final File propertiesFile = new File(propertiesFilePath);
final Properties properties = loadProperties(propertiesFile);
final SingleUserCredentials credentials = new SingleUserCredentials(username, encodedPassword, PROVIDER_CLASS);
final File providersFile = getLoginIdentityProvidersFile(properties);
setCredentials(credentials, providersFile);
System.out.printf("Login Identity Providers Processed [%s]%n", providersFile.getAbsolutePath());
}
private static void setCredentials(final SingleUserCredentials singleUserCredentials, final File providersFile) {
final LoginCredentialsWriter writer = new StandardLoginCredentialsWriter(providersFile);
writer.writeLoginCredentials(singleUserCredentials);
}
private static Properties loadProperties(final File propertiesFile) {
final Properties properties = new Properties();
try (final FileReader reader = new FileReader(propertiesFile)) {
properties.load(reader);
} catch (final IOException e) {
final String message = String.format("Failed to read NiFi Properties [%s]", propertiesFile);
throw new UncheckedIOException(message, e);
}
return properties;
}
private static File getLoginIdentityProvidersFile(final Properties properties) {
return new File(properties.getProperty(PROVIDERS_PROPERTY));
}
}

View File

@ -16,7 +16,7 @@
*/
package org.apache.nifi.authentication.single.user.writer;
import org.apache.nifi.authentication.LoginCredentials;
import org.apache.nifi.authentication.single.user.SingleUserCredentials;
/**
* Writer for Login Identity Providers Configuration
@ -25,7 +25,7 @@ public interface LoginCredentialsWriter {
/**
* Write Login Credentials
*
* @param loginCredentials Login Credentials
* @param singleUserCredentials Single User Credentials
*/
void writeLoginCredentials(LoginCredentials loginCredentials);
void writeLoginCredentials(SingleUserCredentials singleUserCredentials);
}

View File

@ -16,8 +16,7 @@
*/
package org.apache.nifi.authentication.single.user.writer;
import org.apache.nifi.authentication.LoginCredentials;
import org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider;
import org.apache.nifi.authentication.single.user.SingleUserCredentials;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
@ -71,10 +70,10 @@ public class StandardLoginCredentialsWriter implements LoginCredentialsWriter {
}
@Override
public void writeLoginCredentials(final LoginCredentials loginCredentials) {
public void writeLoginCredentials(final SingleUserCredentials singleUserCredentials) {
try {
final File updatedProvidersFile = File.createTempFile(PROVIDERS_PREFIX, PROVIDERS_SUFFIX);
writeLoginCredentials(loginCredentials, updatedProvidersFile);
writeLoginCredentials(singleUserCredentials, updatedProvidersFile);
Files.move(updatedProvidersFile.toPath(), providersFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
throw new UncheckedIOException("Writing Login Identity Providers Failed", e);
@ -83,19 +82,19 @@ public class StandardLoginCredentialsWriter implements LoginCredentialsWriter {
}
}
private void writeLoginCredentials(final LoginCredentials loginCredentials, final File updatedProvidersFile) throws IOException, XMLStreamException {
private void writeLoginCredentials(final SingleUserCredentials singleUserCredentials, final File updatedProvidersFile) throws IOException, XMLStreamException {
try (final OutputStream outputStream = new FileOutputStream(updatedProvidersFile)) {
final XMLEventWriter providersWriter = getProvidersWriter(outputStream);
try (final InputStream inputStream = new FileInputStream(providersFile)) {
final XMLEventReader providersReader = getProvidersReader(inputStream);
updateLoginIdentityProviders(loginCredentials, providersReader, providersWriter);
updateLoginIdentityProviders(singleUserCredentials, providersReader, providersWriter);
providersReader.close();
}
providersWriter.close();
}
}
private void updateLoginIdentityProviders(final LoginCredentials credentials,
private void updateLoginIdentityProviders(final SingleUserCredentials singleUserCredentials,
final XMLEventReader providersReader,
final XMLEventWriter providersWriter) throws XMLStreamException {
boolean processingSingleUserProvider = false;
@ -109,7 +108,7 @@ public class StandardLoginCredentialsWriter implements LoginCredentialsWriter {
providersWriter.add(nextEvent);
if (nextEvent.isCharacters()) {
final String providerClass = nextEvent.asCharacters().getData();
if (SingleUserLoginIdentityProvider.class.getName().equals(providerClass)) {
if (singleUserCredentials.getProviderClass().equals(providerClass)) {
processingSingleUserProvider = true;
}
}
@ -119,9 +118,9 @@ public class StandardLoginCredentialsWriter implements LoginCredentialsWriter {
if (processingSingleUserProvider) {
if (isStartProperty(event, USERNAME_PROPERTY)) {
processProperty(providersReader, providersWriter, credentials.getUsername());
processProperty(providersReader, providersWriter, singleUserCredentials.getUsername());
} else if (isStartProperty(event, PASSWORD_PROPERTY)) {
processProperty(providersReader, providersWriter, credentials.getPassword());
processProperty(providersReader, providersWriter, singleUserCredentials.getPassword());
}
}
}

View File

@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authentication.single.user.command;
import org.apache.commons.io.FilenameUtils;
import org.junit.After;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.junit.Assert.assertTrue;
public class SetSingleUserCredentialsTest {
private static final Pattern BCRYPT_PATTERN = Pattern.compile("\\$2b\\$12\\$.+");
private static final String PROPERTIES_PATH = "/conf/login.nifi.properties";
@After
public void clearProperties() {
System.clearProperty(SetSingleUserCredentials.PROPERTIES_FILE_PATH);
}
@Test
public void testMainNoArguments() {
SetSingleUserCredentials.main(new String[]{});
}
@Test
public void testMainUsernamePasswordUpdated() throws IOException, URISyntaxException {
final Path providersConfiguration = getProvidersConfiguration();
final Path propertiesPath = getNiFiProperties(providersConfiguration);
System.setProperty(SetSingleUserCredentials.PROPERTIES_FILE_PATH, propertiesPath.toString());
final String username = UUID.randomUUID().toString();
final String password = UUID.randomUUID().toString();
SetSingleUserCredentials.main(new String[]{username, password});
assertProvidersUpdated(providersConfiguration, username);
}
private void assertProvidersUpdated(final Path providersConfigurationPath, final String username) throws IOException {
final String providersConfiguration = new String(Files.readAllBytes(providersConfigurationPath), StandardCharsets.UTF_8);
assertTrue("Username not found", providersConfiguration.contains(username));
assertTrue("Encoded Password not found", BCRYPT_PATTERN.matcher(providersConfiguration).find());
}
private Path getNiFiProperties(final Path providersPath) throws IOException, URISyntaxException {
final Path sourcePropertiesPath = Paths.get(SetSingleUserCredentials.class.getResource(PROPERTIES_PATH).toURI());
final List<String> sourceProperties = Files.readAllLines(sourcePropertiesPath);
final List<String> flowProperties = sourceProperties.stream().map(line -> {
if (line.startsWith(SetSingleUserCredentials.PROVIDERS_PROPERTY)) {
final String providersPathProperty = FilenameUtils.separatorsToUnix(providersPath.toString());
return String.format("%s=%s", SetSingleUserCredentials.PROVIDERS_PROPERTY, providersPathProperty);
} else {
return line;
}
}).collect(Collectors.toList());
final Path propertiesPath = Files.createTempFile(SetSingleUserCredentials.class.getSimpleName(), ".properties");
propertiesPath.toFile().deleteOnExit();
Files.write(propertiesPath, flowProperties);
return propertiesPath;
}
private Path getProvidersConfiguration() throws IOException {
final Path providersConfigurationPath = Files.createTempFile(SetSingleUserCredentials.class.getSimpleName(), ".xml");
final File providersConfigurationFile = providersConfigurationPath.toFile();
providersConfigurationFile.deleteOnExit();
try (final InputStream inputStream = SetSingleUserCredentials.class.getResourceAsStream("/conf/standard-login-identity-providers.xml")) {
Files.copy(inputStream, providersConfigurationPath, StandardCopyOption.REPLACE_EXISTING);
}
return providersConfigurationPath;
}
}

View File

@ -16,7 +16,7 @@
*/
package org.apache.nifi.authentication.single.user.writer;
import org.apache.nifi.authentication.LoginCredentials;
import org.apache.nifi.authentication.single.user.SingleUserCredentials;
import org.junit.Test;
import java.io.IOException;
@ -36,6 +36,8 @@ public class StandardLoginCredentialsWriterTest {
private static final String XML_SUFFIX = ".xml";
private static final String PROVIDER_CLASS = SingleUserCredentials.class.getName();
@Test
public void testWriteLoginCredentialsBlankProviders() throws IOException, URISyntaxException {
final Path sourceProvidersPath = Paths.get(getClass().getResource(BLANK_PROVIDERS).toURI());
@ -58,7 +60,7 @@ public class StandardLoginCredentialsWriterTest {
final String username = UUID.randomUUID().toString();
final String password = UUID.randomUUID().toString();
final LoginCredentials credentials = new LoginCredentials(username, password);
final SingleUserCredentials credentials = new SingleUserCredentials(username, password, PROVIDER_CLASS);
writer.writeLoginCredentials(credentials);
final String configuration = new String(Files.readAllBytes(configuredProvidersPath));

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<loginIdentityProviders>
<!-- Default Single User Provider -->
<provider>
<identifier>single-user-provider</identifier>
<class>org.apache.nifi.authentication.single.user.SingleUserCredentials</class>
<property name="Username" />
<property name="Password" />
</provider>
</loginIdentityProviders>

View File

@ -0,0 +1,15 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
nifi.login.identity.provider.configuration.file=./standard-login-identity-providers.xml

View File

@ -17,7 +17,7 @@
<!-- Default Single User Provider -->
<provider>
<identifier>single-user-provider</identifier>
<class>org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider</class>
<class>org.apache.nifi.authentication.single.user.SingleUserCredentials</class>
<property name="Username">USERNAME</property>
<property name="Password">PASSWORD</property>
</provider>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<loginIdentityProviders>
<!-- Default Single User Provider -->
<provider>
<identifier>single-user-provider</identifier>
<class>org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider</class>
<property name="Username">USERNAME</property>
<property name="Password">PASSWORD</property>
</provider>
</loginIdentityProviders>

View File

@ -44,6 +44,7 @@
<module>nifi-security-socket-ssl</module>
<module>nifi-security-utils-api</module>
<module>nifi-security-utils</module>
<module>nifi-single-user-utils</module>
<module>nifi-site-to-site-client</module>
<module>nifi-socket-utils</module>
<module>nifi-utils</module>

View File

@ -15,6 +15,10 @@
## Latest changes
### 1.14.0
- Updated default container configuration to use HTTPS with Single User Authentication
### 1.12.0
- The NiFi Toolkit has been added to the image under the path `/opt/nifi/nifi-toolkit-current` also set as the environment variable `NIFI_TOOLKIT_HOME`
- The installation directory and related environment variables are changed to be version-agnostic to `/opt/nifi/nifi-current`:
@ -62,29 +66,29 @@ The configuration scripts are suitable for at least 1.4.0+.
## Running a container
### Standalone Instance, Unsecured
### Standalone Instance secured with HTTPS and Single User Authentication
The minimum to run a NiFi instance is as follows:
docker run --name nifi \
-p 8080:8080 \
-p 8443:8443 \
-d \
apache/nifi:latest
This will provide a running instance, exposing the instance UI to the host system on at port 8080,
viewable at `http://localhost:8080/nifi`.
This will provide a running instance, exposing the instance UI to the host system on at port 8443,
viewable at `https://localhost:8443/nifi`.
You can also pass in environment variables to change the NiFi communication ports and hostname using the Docker '-e' switch as follows:
docker run --name nifi \
-p 9090:9090 \
-p 9443:9443 \
-d \
-e NIFI_WEB_HTTP_PORT='9090' \
-e NIFI_WEB_HTTPS_PORT='9443' \
apache/nifi:latest
For a list of the environment variables recognised in this build, look into the .sh/secure.sh and .sh/start.sh scripts
### Standalone Instance, Two-Way SSL
In this configuration, the user will need to provide certificates and the associated configuration information.
### Standalone Instance secured with HTTPS and Mutual TLS Authentication
In this configuration, the user will need to provide certificates and associated configuration information.
Of particular note, is the `AUTH` environment variable which is set to `tls`. Additionally, the user must provide an
the DN as provided by an accessing client certificate in the `INITIAL_ADMIN_IDENTITY` environment variable.
This value will be used to seed the instance with an initial user with administrative privileges.
@ -104,8 +108,8 @@ Finally, this command makes use of a volume to provide certificates on the host
-d \
apache/nifi:latest
### Standalone Instance, LDAP
In this configuration, the user will need to provide certificates and the associated configuration information. Optionally,
### Standalone Instance secured with HTTPS and LDAP Authentication
In this configuration, the user will need to provide certificates and associated configuration information. Optionally,
if the LDAP provider of interest is operating in LDAPS or START_TLS modes, certificates will additionally be needed.
Of particular note, is the `AUTH` environment variable which is set to `ldap`. Additionally, the user must provide a
DN as provided by the configured LDAP server in the `INITIAL_ADMIN_IDENTITY` environment variable. This value will be

View File

@ -73,6 +73,10 @@ else
prop_replace 'nifi.web.proxy.host' "${NIFI_WEB_PROXY_HOST}"
fi
# Configure Authorizer and Login Identity Provider
prop_replace 'nifi.security.user.authorizer' "${NIFI_SECURITY_USER_AUTHORIZER:-managed-authorizer}"
prop_replace 'nifi.security.user.login.identity.provider' "${NIFI_SECURITY_USER_LOGIN_IDENTITY_PROVIDER}"
# Establish initial user and an associated admin identity
sed -i -e 's|<property name="Initial User Identity 1"></property>|<property name="Initial User Identity 1">'"${INITIAL_ADMIN_IDENTITY}"'</property>|' ${NIFI_HOME}/conf/authorizers.xml
sed -i -e 's|<property name="Initial Admin Identity"></property>|<property name="Initial Admin Identity">'"${INITIAL_ADMIN_IDENTITY}"'</property>|' ${NIFI_HOME}/conf/authorizers.xml

View File

@ -33,15 +33,31 @@ if [ ! -z "${NIFI_JVM_DEBUGGER}" ]; then
fi
# Establish baseline properties
prop_replace 'nifi.web.http.port' "${NIFI_WEB_HTTP_PORT:-8080}"
prop_replace 'nifi.web.http.host' "${NIFI_WEB_HTTP_HOST:-$HOSTNAME}"
prop_replace 'nifi.web.https.port' "${NIFI_WEB_HTTPS_PORT:-8443}"
prop_replace 'nifi.web.https.host' "${NIFI_WEB_HTTPS_HOST:-$HOSTNAME}"
prop_replace 'nifi.remote.input.host' "${NIFI_REMOTE_INPUT_HOST:-$HOSTNAME}"
prop_replace 'nifi.remote.input.socket.port' "${NIFI_REMOTE_INPUT_SOCKET_PORT:-10000}"
prop_replace 'nifi.remote.input.secure' 'false'
prop_replace 'nifi.remote.input.secure' 'true'
prop_replace 'nifi.cluster.protocol.is.secure' 'true'
# Set nifi-toolkit properties files and baseUrl
"${scripts_dir}/toolkit.sh"
prop_replace 'baseUrl' "http://${NIFI_WEB_HTTP_HOST:-$HOSTNAME}:${NIFI_WEB_HTTP_PORT:-8080}" ${nifi_toolkit_props_file}
prop_replace 'baseUrl' "https://${NIFI_WEB_HTTPS_HOST:-$HOSTNAME}:${NIFI_WEB_HTTPS_PORT:-8443}" ${nifi_toolkit_props_file}
if [ -n "${NIFI_WEB_HTTP_PORT}" ]; then
prop_replace 'nifi.web.https.port' ''
prop_replace 'nifi.web.https.host' ''
prop_replace 'nifi.web.http.port' "${NIFI_WEB_HTTP_PORT}"
prop_replace 'nifi.web.http.host' "${NIFI_WEB_HTTP_HOST:-$HOSTNAME}"
prop_replace 'nifi.remote.input.secure' 'false'
prop_replace 'nifi.cluster.protocol.is.secure' 'false'
prop_replace 'nifi.security.keystore' ''
prop_replace 'nifi.security.keystoreType' ''
prop_replace 'nifi.security.truststore' ''
prop_replace 'nifi.security.truststoreType' ''
prop_replace 'nifi.security.user.login.identity.provider' ''
prop_replace 'baseUrl' "http://${NIFI_WEB_HTTP_HOST:-$HOSTNAME}:${NIFI_WEB_HTTP_PORT}" ${nifi_toolkit_props_file}
fi
prop_replace 'nifi.variable.registry.properties' "${NIFI_VARIABLE_REGISTRY_PROPERTIES:-}"
prop_replace 'nifi.cluster.is.node' "${NIFI_CLUSTER_IS_NODE:-false}"
@ -76,7 +92,7 @@ case ${AUTH} in
ldap)
echo 'Enabling LDAP user authentication'
# Reference ldap-provider in properties
prop_replace 'nifi.security.user.login.identity.provider' 'ldap-provider'
export NIFI_SECURITY_USER_LOGIN_IDENTITY_PROVIDER="ldap-provider"
. "${scripts_dir}/secure.sh"
. "${scripts_dir}/update_login_providers.sh"

View File

@ -40,14 +40,14 @@ docker run -d --name nifi-${TAG}-integration-test apache/nifi:${TAG}
IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nifi-${TAG}-integration-test)
for i in $(seq 1 10) :; do
if docker exec nifi-${TAG}-integration-test bash -c "ss -ntl | grep 8080"; then
if docker exec nifi-${TAG}-integration-test bash -c "ss -ntl | grep 8443"; then
break
fi
sleep 10
done
echo "Checking system diagnostics"
test ${VERSION} = $(docker exec nifi-${TAG}-integration-test bash -c "curl -s $IP:8080/nifi-api/system-diagnostics | jq .systemDiagnostics.aggregateSnapshot.versionInfo.niFiVersion -r")
test ${VERSION} = $(docker exec nifi-${TAG}-integration-test bash -c "curl -s -k $IP:8443/nifi-api/system-diagnostics | jq .systemDiagnostics.aggregateSnapshot.versionInfo.niFiVersion -r")
echo "Checking current user with nifi-toolkit cli"
test "anonymous" = $(docker exec nifi-${TAG}-integration-test bash -c '$NIFI_TOOLKIT_HOME/bin/cli.sh nifi current-user')

View File

@ -73,6 +73,10 @@ else
prop_replace 'nifi.web.proxy.host' "${NIFI_WEB_PROXY_HOST}"
fi
# Configure Authorizer and Login Identity Provider
prop_replace 'nifi.security.user.authorizer' "${NIFI_SECURITY_USER_AUTHORIZER:-managed-authorizer}"
prop_replace 'nifi.security.user.login.identity.provider' "${NIFI_SECURITY_USER_LOGIN_IDENTITY_PROVIDER}"
# Establish initial user and an associated admin identity
sed -i -e 's|<property name="Initial User Identity 1"></property>|<property name="Initial User Identity 1">'"${INITIAL_ADMIN_IDENTITY}"'</property>|' ${NIFI_HOME}/conf/authorizers.xml
sed -i -e 's|<property name="Initial Admin Identity"></property>|<property name="Initial Admin Identity">'"${INITIAL_ADMIN_IDENTITY}"'</property>|' ${NIFI_HOME}/conf/authorizers.xml

View File

@ -33,15 +33,31 @@ if [ ! -z "${NIFI_JVM_DEBUGGER}" ]; then
fi
# Establish baseline properties
prop_replace 'nifi.web.http.port' "${NIFI_WEB_HTTP_PORT:-8080}"
prop_replace 'nifi.web.http.host' "${NIFI_WEB_HTTP_HOST:-$HOSTNAME}"
prop_replace 'nifi.web.https.port' "${NIFI_WEB_HTTPS_PORT:-8443}"
prop_replace 'nifi.web.https.host' "${NIFI_WEB_HTTPS_HOST:-$HOSTNAME}"
prop_replace 'nifi.remote.input.host' "${NIFI_REMOTE_INPUT_HOST:-$HOSTNAME}"
prop_replace 'nifi.remote.input.socket.port' "${NIFI_REMOTE_INPUT_SOCKET_PORT:-10000}"
prop_replace 'nifi.remote.input.secure' 'false'
prop_replace 'nifi.remote.input.secure' 'true'
prop_replace 'nifi.cluster.protocol.is.secure' 'true'
# Set nifi-toolkit properties files and baseUrl
"${scripts_dir}/toolkit.sh"
prop_replace 'baseUrl' "http://${NIFI_WEB_HTTP_HOST:-$HOSTNAME}:${NIFI_WEB_HTTP_PORT:-8080}" ${nifi_toolkit_props_file}
prop_replace 'baseUrl' "https://${NIFI_WEB_HTTPS_HOST:-$HOSTNAME}:${NIFI_WEB_HTTPS_PORT:-8443}" ${nifi_toolkit_props_file}
if [ -n "${NIFI_WEB_HTTP_PORT}" ]; then
prop_replace 'nifi.web.https.port' ''
prop_replace 'nifi.web.https.host' ''
prop_replace 'nifi.web.http.port' "${NIFI_WEB_HTTP_PORT}"
prop_replace 'nifi.web.http.host' "${NIFI_WEB_HTTP_HOST:-$HOSTNAME}"
prop_replace 'nifi.remote.input.secure' 'false'
prop_replace 'nifi.cluster.protocol.is.secure' 'false'
prop_replace 'nifi.security.keystore' ''
prop_replace 'nifi.security.keystoreType' ''
prop_replace 'nifi.security.truststore' ''
prop_replace 'nifi.security.truststoreType' ''
prop_replace 'nifi.security.user.login.identity.provider' ''
prop_replace 'baseUrl' "http://${NIFI_WEB_HTTP_HOST:-$HOSTNAME}:${NIFI_WEB_HTTP_PORT}" ${nifi_toolkit_props_file}
fi
prop_replace 'nifi.variable.registry.properties' "${NIFI_VARIABLE_REGISTRY_PROPERTIES:-}"
prop_replace 'nifi.cluster.is.node' "${NIFI_CLUSTER_IS_NODE:-false}"
@ -76,7 +92,7 @@ case ${AUTH} in
ldap)
echo 'Enabling LDAP user authentication'
# Reference ldap-provider in properties
prop_replace 'nifi.security.user.login.identity.provider' 'ldap-provider'
export NIFI_SECURITY_USER_LOGIN_IDENTITY_PROVIDER="ldap-provider"
. "${scripts_dir}/secure.sh"
. "${scripts_dir}/update_login_providers.sh"

View File

@ -84,15 +84,14 @@ The following table lists the default ports used by NiFi and the corresponding p
[options="header,footer"]
|==================================================================================================================================================
| Function | Property | Default Value
|HTTP Port | `nifi.web.http.port` | `8080`
|HTTPS Port* | `nifi.web.https.port` | `9443`
|HTTPS Port | `nifi.web.https.port` | `8443`
|Remote Input Socket Port* | `nifi.remote.input.socket.port` | `10443`
|Cluster Node Protocol Port* | `nifi.cluster.node.protocol.port` | `11443`
|Cluster Node Load Balancing Port | `nifi.cluster.node.load.balance.port` | `6342`
|Web HTTP Forwarding Port | `nifi.web.http.port.forwarding` | _none_
|==================================================================================================================================================
NOTE: The ports marked with an asterisk (*) have property values that are blank by default in _nifi.properties_. The values shown in the table are the default values for these ports when <<toolkit-guide.adoc#tls_toolkit,TLS Toolkit>> is used to generate _nifi.properties_ for a secured NiFi instance. The default Certificate Authority Port used by <<toolkit-guide.adoc#tls_toolkit,TLS Toolkit>> is `8443`.
NOTE: The ports marked with an asterisk (*) have property values that are blank by default in _nifi.properties_. The values shown in the table are the default values for these ports when <<toolkit-guide.adoc#tls_toolkit,TLS Toolkit>> is used to generate _nifi.properties_ for a secured NiFi instance. The default Certificate Authority Port used by <<toolkit-guide.adoc#tls_toolkit,TLS Toolkit>> is `9443`.
=== Embedded ZooKeeper
The following table lists the default ports used by an <<embedded_zookeeper>> and the corresponding property in the _zookeeper.properties_ file.
@ -252,12 +251,12 @@ NiFi supports user authentication via client certificates, via username/password
Username/password authentication is performed by a 'Login Identity Provider'. The Login Identity Provider is a pluggable mechanism for
authenticating users via their username/password. Which Login Identity Provider to use is configured in the _nifi.properties_ file.
Currently NiFi offers username/password with Login Identity Providers options for <<ldap_login_identity_provider>> and <<kerberos_login_identity_provider>>.
Currently NiFi offers username/password with Login Identity Providers options for <<single_user_identity_provider>>, <<ldap_login_identity_provider>> and <<kerberos_login_identity_provider>>.
The `nifi.login.identity.provider.configuration.file` property specifies the configuration file for Login Identity Providers. By default, this property is set to `./conf/login-identity-providers.xml`.
The `nifi.security.user.login.identity.provider` property indicates which of the configured Login Identity Provider should be
used. By default, this property is not configured meaning that username/password must be explicitly enabled.
used. The default value of this property is `single-user-provider` supporting authentication with a generated username and password.
During OpenId Connect authentication, NiFi will redirect users to login with the Provider before returning to NiFi. NiFi will then
call the Provider to obtain the user identity.
@ -281,6 +280,37 @@ authorization based on the requested resource.
NOTE: NiFi does not perform user authentication over HTTP. Using HTTP, all users will be granted all roles.
[[single_user_identity_provider]]
=== Single User
The default Single User Login Identity Provider supports automated generation of username and password credentials.
The generated username will be a random UUID consisting of 36 characters. The generated password will be a random string
consisting of 32 characters and stored using bcrypt hashing.
The default configuration in _nifi.properties_ enables Single User authentication:
---
nifi.security.user.login.identity.provider=single-user-provider
---
The default _login-identity-providers.xml_ includes a blank provider definition:
---
<provider>
<identifier>single-user-provider</identifier>
<class>org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider</class>
<property name="Username"/>
<property name="Password"/>
</provider>
---
The following command can be used to change the Username and Password:
```
$ ./bin/nifi.sh set-single-user-credentials <username> <password>
```
[[ldap_login_identity_provider]]
=== Lightweight Directory Access Protocol (LDAP)
@ -3516,8 +3546,8 @@ These properties pertain to the web-based User Interface.
|====
|*Property*|*Description*
|`nifi.web.http.host`|The HTTP host. The default value is `127.0.0.1`.
|`nifi.web.http.port`|The HTTP port. The default value is `8080`.
|`nifi.web.http.host`|The HTTP host. The default value is blank.
|`nifi.web.http.port`|The HTTP port. The default value is blank.
|`nifi.web.http.port.forwarding`|The port which forwards incoming HTTP requests to `nifi.web.http.host`. This property is designed to be used with 'port forwarding', when NiFi has to be started by a non-root user for better security, yet it needs to be accessed via low port to go through a firewall. For example, to expose NiFi via HTTP protocol on port 80, but actually listening on port 8080, you need to configure OS level port forwarding such as `iptables` (Linux/Unix) or `pfctl` (macOS) that redirects requests from 80 to 8080. Then set `nifi.web.http.port` as 8080, and `nifi.web.http.port.forwarding` as 80. It is blank by default.
|`nifi.web.http.network.interface`*|The name of the network interface to which NiFi should bind for HTTP requests. It is blank by default. +
+
@ -3529,8 +3559,8 @@ For example, to provide two additional network interfaces, a user could also spe
`nifi.web.http.network.interface.eth1=eth1` +
+
Providing three total network interfaces, including `nifi.web.http.network.interface.default`.
|`nifi.web.https.host`|The HTTPS host. It is blank by default.
|`nifi.web.https.port`|The HTTPS port. It is blank by default. When configuring NiFi to run securely, this port should be configured.
|`nifi.web.https.host`|The HTTPS host. The default value is `127.0.0.1`.
|`nifi.web.https.port`|The HTTPS port. The default value is `8443`.
|`nifi.web.https.port.forwarding`|Same as `nifi.web.http.port.forwarding`, but with HTTPS for secure communication. It is blank by default.
|`nifi.web.https.ciphersuites.include`|Cipher suites used to initialize the SSLContext of the Jetty HTTPS port. If unspecified, the runtime SSLContext defaults are used.
|`nifi.web.https.ciphersuites.exclude`|Cipher suites that may not be used by an SSL client to establish a connection to Jetty. If unspecified, the runtime SSLContext defaults are used.

View File

@ -119,13 +119,35 @@ and `sudo service nifi stop`. Additionally, the running status can be checked vi
== I Started NiFi. Now What?
Now that NiFi has been started, we can bring up the User Interface (UI) in order to create and monitor our dataflow.
To get started, open a web browser and navigate to link:http://localhost:8080/nifi[`http://localhost:8080/nifi`^]. The port can be changed by
editing the `nifi.properties` file in the NiFi `conf` directory, but the default port is 8080.
The default installation generates a random username and password, writing the generated values to the application log.
The application log is located in `logs/nifi-app.log` under the installation directory. The log file will contain lines
with `Generated Username [USERNAME]` and `Generated Password [PASSWORD]` indicating the credentials needed for access.
Search the application log for those lines and record the generated values in a secure location.
The following command can be used to change the username and password:
```
$ ./bin/nifi.sh set-single-user-credentials <username> <password>
```
Now that NiFi has been started, we can bring up the User Interface (UI) in order to create and monitor our dataflow.
To get started, open a web browser and navigate to link:https://localhost:8443/nifi[`https://localhost:8443/nifi`^]. The port can be changed by
editing the `nifi.properties` file in the NiFi `conf` directory, but the default port is 8443.
The web browser will display a warning message indicating a potential security risk due to the self-signed
certificate NiFi generated during initialization. Accepting the potential security risk and continuing to load
the interface is an option for development installations. The self-signed certificate will expire after 60 days.
Production deployments should provision a certificate from a trusted authority and update the NiFi keystore and truststore configuration.
Accessing NiFi after accepting the self-signed certificate will display the login screen.
image:nifi-login.png["Login"]
Using the generated credentials, enter the generated username in the `User` field
and the generated password in the `Password` field, then press `LOG IN` to access the system.
This will bring up the User Interface, which at this point is a blank canvas for orchestrating a dataflow:
image:new-flow.png["New Flow"]
image:nifi-flow-authenticated.png["New Flow Authenticated"]
The UI has multiple tools to create and manage your first dataflow:

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

View File

@ -1008,7 +1008,7 @@ The following are available options:
* `-g`,`--differentKeyAndKeystorePasswords` Use different generated password for the key and the keystore
* `-h`,`--help` Print help and exit
* `-k`,`--keySize <arg>` Number of bits for generated keys (default: `2048`)
* `-p`,`--PORT <arg>` The port for the Certificate Authority to listen on (default: `8443`)
* `-p`,`--PORT <arg>` The port for the Certificate Authority to listen on (default: `9443`)
* `-s`,`--signingAlgorithm <arg>` Algorithm to use for signing certificates (default: `SHA256WITHRSA`)
* `-T`,`--keyStoreType <arg>` The type of keystores to generate (default: `jks`)
* `-t`,`--token <arg>` The token to use to prevent MITM (required and must be same as one used by clients)
@ -1033,7 +1033,7 @@ The following are available options:
* `-g`,`--differentKeyAndKeystorePasswords` Use different generated password for the key and the keystore
* `-h`,`--help` Print help and exit
* `-k`,`--keySize <arg>` Number of bits for generated keys (default: `2048`)
* `-p`,`--PORT <arg>` The port to use to communicate with the Certificate Authority (default: `8443`)
* `-p`,`--PORT <arg>` The port to use to communicate with the Certificate Authority (default: `9443`)
* `--subjectAlternativeNames <arg>` Comma-separated list of domains to use as Subject Alternative Names in the certificate
* `-T`,`--keyStoreType <arg>` The type of keystores to generate (default: `jks`)
* `-t`,`--token <arg>` The token to use to prevent MITM (required and must be same as one used by CA)

View File

@ -139,8 +139,9 @@ application and highlights the different segments of the UI. Each segment is dis
in the document.
When the application is started, the user is able to navigate to the UI by going to the default address of
`http://<hostname>:8080/nifi` in a web browser. There are no permissions configured by default, so anyone is
able to view and modify the dataflow. For information on securing the system, see the link:administration-guide.html[System Administrators Guide].
`https://localhost:8443/nifi` in a web browser. The default configuration generates a username and password
with full system administration privileges.
For information on securing the system, see the link:administration-guide.html[System Administrators Guide].
When a DFM navigates to the UI for the first time, a blank canvas is provided on which a dataflow can be built:
@ -1776,7 +1777,7 @@ NiFi provides various mechanisms for getting around a dataflow. The <<User_Inter
A hyperlink can be used to navigate directly to a component on the NiFi canvas. This is especially useful when link:administration-guide.html#multi-tenant-authorization[Multi-Tenant Authorization] is configured. For example, a URL can be given to a user to direct them to the specific process group to which they have privileges.
The default URL for a NiFI instance is `http://<hostname>:8080/nifi`, which points to the root process group. When a component is selected on the canvas, the URL is updated with the component's process group id and component id in the form `http://<hostname>:8080/nifi/?processGroupId=<UUID>&componentIds=<UUIDs>`. In the following screenshot, the GenerateFlowFile processor in the process group PG1 is the selected component:
The default URL for a NiFI instance is `https://localhost:8443/nifi`, which points to the root process group. When a component is selected on the canvas, the URL is updated with the component's process group id and component id in the form `https://localhost:8443/nifi/?processGroupId=<UUID>&componentIds=<UUIDs>`. In the following screenshot, the GenerateFlowFile processor in the process group PG1 is the selected component:
image::component-linking-processor.png["Component Linking Processor Example"]

View File

@ -95,6 +95,7 @@
<nifi.h2.url.append>;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE</nifi.h2.url.append>
<nifi.remote.input.socket.port>9990</nifi.remote.input.socket.port>
<nifi.remote.input.secure>true</nifi.remote.input.secure>
<!-- persistent provenance repository properties -->
<nifi.provenance.repository.implementation>org.apache.nifi.provenance.WriteAheadProvenanceRepository</nifi.provenance.repository.implementation>
@ -131,11 +132,11 @@
<nifi.status.repository.questdb.persist.location>./status_repository</nifi.status.repository.questdb.persist.location>
<!-- nifi.properties: web properties -->
<nifi.web.http.host>127.0.0.1</nifi.web.http.host>
<nifi.web.http.port>8080</nifi.web.http.port>
<nifi.web.http.host />
<nifi.web.http.port />
<nifi.web.http.network.interface.default />
<nifi.web.https.host />
<nifi.web.https.port />
<nifi.web.https.host>127.0.0.1</nifi.web.https.host>
<nifi.web.https.port>8443</nifi.web.https.port>
<nifi.web.https.network.interface.default />
<nifi.jetty.work.dir>./work/jetty</nifi.jetty.work.dir>
<nifi.web.jetty.threads>200</nifi.web.jetty.threads>
@ -150,22 +151,16 @@
<!-- nifi.properties: security properties -->
<nifi.security.autoreload.enabled>false</nifi.security.autoreload.enabled>
<nifi.security.autoreload.interval>10 secs</nifi.security.autoreload.interval>
<!-- Use these values once we change default configuration to be HTTPS
<nifi.security.keystore>./conf/keystore.p12</nifi.security.keystore>
<nifi.security.keystoreType>PKCS12</nifi.security.keystoreType> -->
<nifi.security.keystore />
<nifi.security.keystoreType />
<nifi.security.keystoreType>PKCS12</nifi.security.keystoreType>
<nifi.security.keystorePasswd />
<nifi.security.keyPasswd />
<!-- Use these values once we change default configuration to be HTTPS
<nifi.security.truststore>./conf/truststore.p12</nifi.security.truststore>
<nifi.security.truststoreType>PKCS12</nifi.security.truststoreType> -->
<nifi.security.truststore />
<nifi.security.truststoreType />
<nifi.security.truststoreType>PKCS12</nifi.security.truststoreType>
<nifi.security.truststorePasswd />
<nifi.security.user.authorizer>managed-authorizer</nifi.security.user.authorizer>
<nifi.security.user.authorizer>single-user-authorizer</nifi.security.user.authorizer>
<nifi.security.allow.anonymous.authentication>false</nifi.security.allow.anonymous.authentication>
<nifi.security.user.login.identity.provider />
<nifi.security.user.login.identity.provider>single-user-provider</nifi.security.user.login.identity.provider>
<nifi.security.x509.principal.extractor />
<nifi.security.ocsp.responder.url />
<nifi.security.ocsp.responder.certificate />

View File

@ -349,6 +349,16 @@ run() {
return;
fi
if [ "$1" = "set-single-user-credentials" ]; then
run_command="'${JAVA}' -cp '${BOOTSTRAP_CLASSPATH}' '-Dnifi.properties.file.path=${NIFI_HOME}/conf/nifi.properties' 'org.apache.nifi.authentication.single.user.command.SetSingleUserCredentials'"
eval "cd ${NIFI_HOME}"
shift
eval "${run_command}" '"$@"'
EXIT_STATUS=$?
echo
return;
fi
if [ "$1" = "stateless" ]; then
STATELESS_JAVA_OPTS="${STATELESS_JAVA_OPTS:=-Xms1024m -Xmx1024m}"
@ -445,7 +455,7 @@ case "$1" in
install "$@"
;;
start|stop|decommission|run|status|is_loaded|dump|diagnostics|env|stateless|set-sensitive-properties-key)
start|stop|decommission|run|status|is_loaded|dump|diagnostics|env|stateless|set-sensitive-properties-key|set-single-user-credentials)
main "$@"
;;
@ -455,6 +465,6 @@ case "$1" in
run "start"
;;
*)
echo "Usage nifi {start|stop|decommission|run|restart|status|dump|diagnostics|install|stateless|set-sensitive-properties-key}"
echo "Usage nifi {start|stop|decommission|run|restart|status|dump|diagnostics|install|stateless|set-sensitive-properties-key|set-single-user-credentials}"
;;
esac

View File

@ -385,4 +385,15 @@
<property name="Node Identity 1"></property>
</authorizer>
-->
<!--
Single User Authorizer requires the configuration of the SingleUserLoginIdentityProvider
in login-identity-provider.xml and in nifi.properties
The managed-authorizer should be used for production deployments
-->
<authorizer>
<identifier>single-user-authorizer</identifier>
<class>org.apache.nifi.authorization.single.user.SingleUserAuthorizer</class>
</authorizer>
</authorizers>

View File

@ -19,6 +19,22 @@
must be specified in the nifi.properties file.
-->
<loginIdentityProviders>
<!--
Single User Login Identity Provider supporting automated generation of Username and Password
The provider will write the following log messages when 'Username' and 'Password' are empty:
Generated Username [USERNAME]
Generated Password [PASSWORD]
The 'Username' will be a random UUID and the 'Password' will be stored using bcrypt hashing
-->
<provider>
<identifier>single-user-provider</identifier>
<class>org.apache.nifi.authentication.single.user.SingleUserLoginIdentityProvider</class>
<property name="Username"/>
<property name="Password"/>
</provider>
<!--
Identity Provider for users logging in with username/password against an LDAP server.

View File

@ -134,7 +134,7 @@ nifi.status.repository.questdb.persist.location=${nifi.status.repository.questdb
# Site to Site properties
nifi.remote.input.host=
nifi.remote.input.secure=false
nifi.remote.input.secure=${nifi.remote.input.secure}
nifi.remote.input.socket.port=
nifi.remote.input.http.enabled=true
nifi.remote.input.http.transaction.ttl=30 sec

View File

@ -42,9 +42,9 @@
<version>1.14.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>at.favre.lib</groupId>
<artifactId>bcrypt</artifactId>
<version>0.9.0</version>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-single-user-utils</artifactId>
<version>1.14.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -53,13 +53,13 @@ public class SingleUserLoginIdentityProvider implements LoginIdentityProvider {
private static final int RANDOM_BYTE_LENGTH = 24;
private static final long EXPIRATION = TimeUnit.HOURS.toMillis(1);
private static final long EXPIRATION = TimeUnit.HOURS.toMillis(8);
protected PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private File loginIdentityProviderConfigurationFile;
private LoginCredentials configuredCredentials;
private SingleUserCredentials configuredCredentials;
/**
* Set NiFi Properties using method injection
@ -124,7 +124,7 @@ public class SingleUserLoginIdentityProvider implements LoginIdentityProvider {
}
} else {
final String username = configurationContext.getProperty(USERNAME_PROPERTY);
configuredCredentials = new LoginCredentials(username, password);
configuredCredentials = new SingleUserCredentials(username, password, getClass().getName());
}
}
@ -147,15 +147,16 @@ public class SingleUserLoginIdentityProvider implements LoginIdentityProvider {
return new StandardLoginCredentialsWriter(loginIdentityProviderConfigurationFile);
}
private LoginCredentials generateLoginCredentials() throws IOException {
private SingleUserCredentials generateLoginCredentials() throws IOException {
final String username = UUID.randomUUID().toString();
final String password = generatePassword();
final String separator = System.lineSeparator();
LOGGER.info("{}{}Generated Username [{}]{}Generated Password [{}]{}", separator, separator, username, separator, password, separator);
LOGGER.info("Run the following command to change credentials: nifi.sh set-single-user-credentials USERNAME PASSWORD");
final String hashedPassword = passwordEncoder.encode(password.toCharArray());
return new LoginCredentials(username, hashedPassword);
return new SingleUserCredentials(username, hashedPassword, getClass().getName());
}
private boolean isPasswordVerified(final String password) {

View File

@ -43,7 +43,7 @@ RUN chown -R nifi:nifi ${NIFI_TOOLKIT_BASE_DIR}
USER nifi
# Default port for TLS Toolkit CA Server
EXPOSE 8443
EXPOSE 9443
WORKDIR ${NIFI_TOOLKIT_HOME}

View File

@ -46,7 +46,7 @@ RUN apk add --update curl bash jq openssl \
USER nifi
# Default port for TLS Toolkit CA Server
EXPOSE 8443
EXPOSE 9443
WORKDIR ${NIFI_TOOLKIT_HOME}

View File

@ -3,7 +3,7 @@
"keyStoreType" : "jks",
"token" : "myTestTokenUseSomethingStronger",
"dn" : "CN=otherHostname,OU=NIFI",
"port" : 8443,
"port" : 9443,
"caHostname" : "localhost",
"trustStore" : "clientTrustStore",
"trustStoreType" : "jks",

View File

@ -3,7 +3,7 @@
"keyStoreType" : "jks",
"token" : "myTestTokenUseSomethingStronger",
"caHostname" : "localhost",
"port" : 8443,
"port" : 9443,
"days" : 825,
"keySize" : 2048,
"keyPairAlgorithm" : "RSA",

View File

@ -27,7 +27,7 @@ import org.apache.nifi.util.StringUtils;
public class TlsConfig {
public static final String DEFAULT_HOSTNAME = "localhost";
public static final String DEFAULT_KEY_STORE_TYPE = "jks";
public static final int DEFAULT_PORT = 8443;
public static final int DEFAULT_PORT = 9443;
public static final int DEFAULT_DAYS = 825;
public static final int DEFAULT_KEY_SIZE = 2048;
public static final String DEFAULT_KEY_PAIR_ALGORITHM = "RSA";

View File

@ -56,7 +56,7 @@ public class TlsToolkitGetStatusCommandLine extends BaseCommandLine {
public TlsToolkitGetStatusCommandLine() {
super(DESCRIPTION);
addOptionWithArg("u", URL_ARG, "The full url to connect to, for example: https://localhost:8443/v1/api");
addOptionWithArg("u", URL_ARG, "The full url to connect to, for example: https://localhost:9443/v1/api");
addOptionWithArg("ks", KEYSTORE_ARG, "The key store to use");
addOptionWithArg("kst", KEYSTORE_TYPE_ARG, "The type of key store being used (PKCS12 or JKS)", DEFAULT_KEYSTORE_TYPE);
addOptionWithArg("ksp", KEYSTORE_PASSWORD_ARG, "The password of the key store being used");

View File

@ -29,7 +29,7 @@ incrementing.properties= \
nifi.remote.input.socket.port, \
nifi.cluster.node.protocol.port
nifi.web.https.port=9443
nifi.web.https.port=8443
nifi.remote.input.socket.port=10443
nifi.cluster.node.protocol.port=11443