This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new e436381 NIFI-8975 Integrate KerberosUserService into HBase
processors/services
e436381 is described below
commit e436381c3afb9585c8c6299eddb1e71dcb7666f1
Author: Bryan Bende <[email protected]>
AuthorDate: Fri Aug 20 12:56:34 2021 -0400
NIFI-8975 Integrate KerberosUserService into HBase processors/services
This closes #5322
Signed-off-by: David Handermann <[email protected]>
---
.../nifi/security/krb/KerberosLoginException.java | 32 ++++++
.../org/apache/nifi/security/krb/KerberosUser.java | 13 +--
.../nifi/security/krb/AbstractKerberosUser.java | 20 ++--
.../apache/nifi/security/krb/KerberosAction.java | 9 +-
.../java/org/apache/nifi/hadoop/SecurityUtil.java | 44 +++++---
.../processors/hadoop/AbstractHadoopProcessor.java | 19 +---
.../nifi-hbase-processors/pom.xml | 5 +-
.../org/apache/nifi/hbase/AbstractPutHBase.java | 8 +-
.../apache/nifi/dbcp/hive/HiveConnectionPool.java | 4 +-
.../nifi/processors/hive/PutHiveStreaming.java | 4 +-
.../apache/nifi/dbcp/hive/Hive3ConnectionPool.java | 4 +-
.../nifi/processors/hive/PutHive3Streaming.java | 4 +-
.../nifi/dbcp/hive/Hive_1_1ConnectionPool.java | 4 +-
.../processors/kudu/AbstractKuduProcessor.java | 4 +-
.../apache/nifi/processors/solr/SolrProcessor.java | 4 +-
.../org/apache/nifi/dbcp/DBCPConnectionPool.java | 5 +-
.../apache/nifi/dbcp/GroovyDBCPServiceTest.groovy | 14 +--
.../apache/nifi/dbcp/HadoopDBCPConnectionPool.java | 5 +-
.../nifi-hbase_1_1_2-client-service/pom.xml | 6 +-
.../nifi/hbase/HBase_1_1_2_ClientService.java | 117 ++++++++++++++------
.../nifi/hbase/TestHBase_1_1_2_ClientService.java | 78 +++++++++++++
.../nifi-hbase_2-client-service/pom.xml | 7 +-
.../apache/nifi/hbase/HBase_2_ClientService.java | 121 +++++++++++++++------
.../nifi/hbase/TestHBase_2_ClientService.java | 78 +++++++++++++
.../hortonworks/KerberosUserLogin.java | 2 +-
.../SchemaRegistryClientWithKerberosPassword.java | 3 +-
26 files changed, 452 insertions(+), 162 deletions(-)
diff --git
a/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosLoginException.java
b/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosLoginException.java
new file mode 100644
index 0000000..f064d33
--- /dev/null
+++
b/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosLoginException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.security.krb;
+
+/**
+ * Exception thrown by KerberosUser when an error happens during login/logout.
+ */
+public class KerberosLoginException extends RuntimeException {
+
+ public KerberosLoginException(String message) {
+ super(message);
+ }
+
+ public KerberosLoginException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git
a/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
b/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
index 631f445..f6b0f35 100644
---
a/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
+++
b/nifi-commons/nifi-security-kerberos-api/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
@@ -17,7 +17,6 @@
package org.apache.nifi.security.krb;
import javax.security.auth.login.AppConfigurationEntry;
-import javax.security.auth.login.LoginException;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@@ -30,16 +29,16 @@ public interface KerberosUser {
/**
* Performs a login for the given user.
*
- * @throws LoginException if the login fails
+ * @throws KerberosLoginException if the login fails
*/
- void login() throws LoginException;
+ void login();
/**
* Performs a logout for the given user.
*
- * @throws LoginException if the logout fails
+ * @throws KerberosLoginException if the logout fails
*/
- void logout() throws LoginException;
+ void logout();
/**
* Executes the given action as the given user.
@@ -107,9 +106,9 @@ public interface KerberosUser {
* Performs a re-login if the TGT is close to expiration.
*
* @return true if a relogin was performed, false otherwise
- * @throws LoginException if the relogin fails
+ * @throws KerberosLoginException if the relogin fails
*/
- boolean checkTGTAndRelogin() throws LoginException;
+ boolean checkTGTAndRelogin();
/**
* @return true if this user is currently logged in, false otherwise
diff --git
a/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
b/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
index 3d7c96c..6fe46b6 100644
---
a/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
+++
b/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
@@ -75,10 +75,10 @@ public abstract class AbstractKerberosUser implements
KerberosUser {
/**
* Performs a login using the specified principal and keytab.
*
- * @throws LoginException if the login fails
+ * @throws KerberosLoginException if the login fails
*/
@Override
- public synchronized void login() throws LoginException {
+ public synchronized void login() {
if (isLoggedIn()) {
return;
}
@@ -100,10 +100,8 @@ public abstract class AbstractKerberosUser implements
KerberosUser {
loginContext.login();
loggedIn.set(true);
LOGGER.debug("Successful login for {}", new Object[]{principal});
- } catch (LoginException le) {
- LoginException loginException = new LoginException("Unable to
login with " + principal + " due to: " + le.getMessage());
- loginException.setStackTrace(le.getStackTrace());
- throw loginException;
+ } catch (final LoginException le) {
+ throw new KerberosLoginException("Unable to login with " +
principal + " due to: " + le.getMessage(), le);
}
}
@@ -134,10 +132,10 @@ public abstract class AbstractKerberosUser implements
KerberosUser {
/**
* Performs a logout of the current user.
*
- * @throws LoginException if the logout fails
+ * @throws KerberosLoginException if the logout fails
*/
@Override
- public synchronized void logout() throws LoginException {
+ public synchronized void logout() {
if (!isLoggedIn()) {
return;
}
@@ -148,8 +146,8 @@ public abstract class AbstractKerberosUser implements
KerberosUser {
LOGGER.debug("Successful logout for {}", new Object[]{principal});
loginContext = null;
- } catch (LoginException e) {
- throw new LoginException("Logout failed due to: " +
e.getMessage());
+ } catch (final LoginException e) {
+ throw new KerberosLoginException("Logout failed due to: " +
e.getMessage(), e);
}
}
@@ -195,7 +193,7 @@ public abstract class AbstractKerberosUser implements
KerberosUser {
* @throws LoginException if an error happens performing the re-login
*/
@Override
- public synchronized boolean checkTGTAndRelogin() throws LoginException {
+ public synchronized boolean checkTGTAndRelogin() {
final KerberosTicket tgt = getTGT();
if (tgt == null) {
LOGGER.debug("TGT for {} was not found, performing logout/login",
principal);
diff --git
a/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
b/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
index dce2e06..ee1bfbf 100644
---
a/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
+++
b/nifi-commons/nifi-security-kerberos/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
@@ -20,7 +20,6 @@ import org.apache.commons.lang3.Validate;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.processor.exception.ProcessException;
-import javax.security.auth.login.LoginException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@@ -60,7 +59,7 @@ public class KerberosAction<T> {
try {
kerberosUser.login();
logger.info("Successful login for {}", new
Object[]{kerberosUser.getPrincipal()});
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Login failed due to: " +
e.getMessage(), e);
}
}
@@ -68,7 +67,7 @@ public class KerberosAction<T> {
// check if we need to re-login, will only happen if re-login window
is reached (80% of TGT life)
try {
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Relogin check failed due to: " +
e.getMessage(), e);
}
@@ -79,7 +78,7 @@ public class KerberosAction<T> {
} else {
result = kerberosUser.doAs(action, contextClassLoader);
}
- } catch (SecurityException se) {
+ } catch (final SecurityException se) {
logger.info("Privileged action failed, attempting relogin and
retrying...");
logger.debug("", se);
@@ -90,7 +89,7 @@ public class KerberosAction<T> {
} catch (Exception e) {
throw new ProcessException("Retrying privileged action failed
due to: " + e.getMessage(), e);
}
- } catch (PrivilegedActionException pae) {
+ } catch (final PrivilegedActionException pae) {
final Exception cause = pae.getException();
throw new ProcessException("Privileged action failed due to: " +
cause.getMessage(), cause);
}
diff --git
a/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/hadoop/SecurityUtil.java
b/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/hadoop/SecurityUtil.java
index 6bf0aa5..0a9c023 100644
---
a/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/hadoop/SecurityUtil.java
+++
b/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/hadoop/SecurityUtil.java
@@ -20,12 +20,11 @@ import org.apache.commons.lang3.Validate;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.nifi.logging.ComponentLog;
-import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosUser;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.security.AccessControlContext;
import java.security.AccessController;
@@ -110,9 +109,9 @@ public class SecurityUtil {
UserGroupInformation.setLoginUser(ugi);
return ugi;
});
- } catch (PrivilegedActionException e) {
+ } catch (final PrivilegedActionException e) {
throw new IOException("Unable to acquire UGI for KerberosUser: " +
e.getException().getLocalizedMessage(), e.getException());
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new IOException("Unable to acquire UGI for KerberosUser: " +
e.getLocalizedMessage(), e);
}
}
@@ -149,7 +148,16 @@ public class SecurityUtil {
return
KERBEROS.equalsIgnoreCase(config.get(HADOOP_SECURITY_AUTHENTICATION));
}
- public static <T> T callWithUgi(UserGroupInformation ugi,
PrivilegedExceptionAction<T> action) throws IOException {
+ /**
+ * Helper method to execute the given action as the given user.
+ *
+ * @param ugi the user
+ * @param action the action
+ * @param <T> the result type of the action
+ * @return the result of the action
+ * @throws IOException if the action was interrupted
+ */
+ public static <T> T callWithUgi(final UserGroupInformation ugi, final
PrivilegedExceptionAction<T> action) throws IOException {
try {
T result;
if (ugi == null) {
@@ -171,19 +179,21 @@ public class SecurityUtil {
}
}
- public static void checkTGTAndRelogin(ComponentLog log, KerberosUser
kerberosUser) {
- log.trace("getting UGI instance");
- if (kerberosUser != null) {
- // if there's a KerberosUser associated with this UGI, check the
TGT and relogin if it is close to expiring
- log.debug("kerberosUser is " + kerberosUser);
- try {
- log.debug("checking TGT on kerberosUser " + kerberosUser);
- kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
- throw new ProcessException("Unable to relogin with kerberos
credentials for " + kerberosUser.getPrincipal(), e);
- }
- } else {
+ /**
+ * Helper method to call checkTGTAndRelogin on a given KerberosUser that
may be null.
+ *
+ * @param log the logger
+ * @param kerberosUser the kerberos user
+ * @throws KerberosLoginException if an error occurs when
checkTGTAndRelogin calls login or logout
+ */
+ public static void checkTGTAndRelogin(final ComponentLog log, final
KerberosUser kerberosUser) {
+ if (kerberosUser == null) {
log.debug("kerberosUser was null, will not refresh TGT with
KerberosUser");
+ return;
}
+
+ log.debug("checking TGT on kerberosUser {}", kerberosUser);
+ kerberosUser.checkTGTAndRelogin();
}
+
}
diff --git
a/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/processors/hadoop/AbstractHadoopProcessor.java
b/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/processors/hadoop/AbstractHadoopProcessor.java
index 2aebf83..fd8dd4d 100644
---
a/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/processors/hadoop/AbstractHadoopProcessor.java
+++
b/nifi-nar-bundles/nifi-extension-utils/nifi-hadoop-utils/src/main/java/org/apache/nifi/processors/hadoop/AbstractHadoopProcessor.java
@@ -43,14 +43,12 @@ import org.apache.nifi.kerberos.KerberosUserService;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessorInitializationContext;
-import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.security.krb.KerberosKeytabUser;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import javax.net.SocketFactory;
-import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
@@ -360,7 +358,7 @@ public abstract class AbstractHadoopProcessor extends
AbstractProcessor {
if (kerberosUser != null) {
try {
kerberosUser.logout();
- } catch (LoginException e) {
+ } catch (final Exception e) {
getLogger().warn("Error logging out KerberosUser: {}",
e.getMessage(), e);
}
}
@@ -623,19 +621,8 @@ public abstract class AbstractHadoopProcessor extends
AbstractProcessor {
protected UserGroupInformation getUserGroupInformation() {
getLogger().trace("getting UGI instance");
- if (hdfsResources.get().getKerberosUser() != null) {
- // if there's a KerberosUser associated with this UGI, check the
TGT and relogin if it is close to expiring
- KerberosUser kerberosUser = hdfsResources.get().getKerberosUser();
- getLogger().debug("kerberosUser is " + kerberosUser);
- try {
- getLogger().debug("checking TGT on kerberosUser " +
kerberosUser);
- kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
- throw new ProcessException("Unable to relogin with kerberos
credentials for " + kerberosUser.getPrincipal(), e);
- }
- } else {
- getLogger().debug("kerberosUser was null, will not refresh TGT
with KerberosUser");
- }
+ // if there is a KerberosUser associated with UGI, call
checkTGTAndRelogin to ensure UGI's underlying Subject has a valid ticket
+ SecurityUtil.checkTGTAndRelogin(getLogger(),
hdfsResources.get().getKerberosUser());
return hdfsResources.get().getUserGroupInformation();
}
diff --git a/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/pom.xml
b/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/pom.xml
index 13fc17f..45dcc9b 100644
--- a/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/pom.xml
+++ b/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/pom.xml
@@ -31,8 +31,11 @@
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-security-kerberos-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
<artifactId>nifi-distributed-cache-client-service-api</artifactId>
- <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
diff --git
a/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/src/main/java/org/apache/nifi/hbase/AbstractPutHBase.java
b/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/src/main/java/org/apache/nifi/hbase/AbstractPutHBase.java
index d5c9acc..614b20d 100644
---
a/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/src/main/java/org/apache/nifi/hbase/AbstractPutHBase.java
+++
b/nifi-nar-bundles/nifi-hbase-bundle/nifi-hbase-processors/src/main/java/org/apache/nifi/hbase/AbstractPutHBase.java
@@ -32,6 +32,7 @@ import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.security.krb.KerberosLoginException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -221,9 +222,11 @@ public abstract class AbstractPutHBase extends
AbstractProcessor {
try {
clientService.put(entry.getKey(), entry.getValue());
successes.addAll(entry.getValue());
- } catch (Exception e) {
+ } catch (final KerberosLoginException kle) {
+ getLogger().error("Failed to connect to HBase due to {}:
Rolling back session, and penalizing flow files", kle, kle);
+ session.rollback(true);
+ } catch (final Exception e) {
getLogger().error(e.getMessage(), e);
-
for (PutFlowFile putFlowFile : entry.getValue()) {
getLogger().error("Failed to send {} to HBase due to {};
routing to failure", new Object[]{putFlowFile.getFlowFile(), e});
final FlowFile failure =
session.penalize(putFlowFile.getFlowFile());
@@ -240,7 +243,6 @@ public abstract class AbstractPutHBase extends
AbstractProcessor {
final String details = "Put " + putFlowFile.getColumns().size() +
" cells to HBase";
session.getProvenanceReporter().send(putFlowFile.getFlowFile(),
getTransitUri(putFlowFile), details, sendMillis);
}
-
}
protected String getTransitUri(PutFlowFile putFlowFile) {
diff --git
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/dbcp/hive/HiveConnectionPool.java
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/dbcp/hive/HiveConnectionPool.java
index 959c31b..c7bb424 100644
---
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/dbcp/hive/HiveConnectionPool.java
+++
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/dbcp/hive/HiveConnectionPool.java
@@ -44,13 +44,13 @@ import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.apache.nifi.util.hive.AuthenticationFailedException;
import org.apache.nifi.util.hive.HiveConfigurator;
import org.apache.nifi.util.hive.ValidationResources;
-import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
@@ -401,7 +401,7 @@ public class HiveConnectionPool extends
AbstractControllerService implements Hiv
try {
getLogger().debug("checking TGT on kerberosUser [{}]",
new Object[]{kerberosUser});
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Unable to relogin with
kerberos credentials for " + kerberosUser.getPrincipal(), e);
}
} else {
diff --git
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/processors/hive/PutHiveStreaming.java
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/processors/hive/PutHiveStreaming.java
index 9173486..f1a3679 100644
---
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/processors/hive/PutHiveStreaming.java
+++
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive-processors/src/main/java/org/apache/nifi/processors/hive/PutHiveStreaming.java
@@ -65,6 +65,7 @@ import
org.apache.nifi.processor.util.pattern.ExceptionHandler;
import org.apache.nifi.processor.util.pattern.RollbackOnFailure;
import org.apache.nifi.processor.util.pattern.RoutingResult;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.apache.nifi.util.hive.AuthenticationFailedException;
@@ -75,7 +76,6 @@ import org.apache.nifi.util.hive.HiveWriter;
import org.apache.nifi.util.hive.ValidationResources;
import org.xerial.snappy.Snappy;
-import javax.security.auth.login.LoginException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -1173,7 +1173,7 @@ public class PutHiveStreaming extends
AbstractSessionFactoryProcessor {
try {
getLogger().debug("checking TGT on kerberosUser [{}]", new
Object[] {kerberosUser});
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Unable to relogin with kerberos
credentials for " + kerberosUser.getPrincipal(), e);
}
} else {
diff --git
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive3ConnectionPool.java
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive3ConnectionPool.java
index ef03c76..75ad406 100644
---
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive3ConnectionPool.java
+++
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive3ConnectionPool.java
@@ -45,13 +45,13 @@ import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.apache.nifi.util.hive.AuthenticationFailedException;
import org.apache.nifi.util.hive.HiveConfigurator;
import org.apache.nifi.util.hive.ValidationResources;
-import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
@@ -502,7 +502,7 @@ public class Hive3ConnectionPool extends
AbstractControllerService implements Hi
try {
getLogger().debug("checking TGT on kerberosUser " +
kerberosUser);
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Unable to relogin with
kerberos credentials for " + kerberosUser.getPrincipal(), e);
}
} else {
diff --git
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/processors/hive/PutHive3Streaming.java
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/processors/hive/PutHive3Streaming.java
index b7a3573..ad5555e 100644
---
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/processors/hive/PutHive3Streaming.java
+++
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive3-processors/src/main/java/org/apache/nifi/processors/hive/PutHive3Streaming.java
@@ -59,6 +59,7 @@ import
org.apache.nifi.processor.util.pattern.DiscontinuedException;
import org.apache.nifi.processor.util.pattern.RollbackOnFailure;
import
org.apache.nifi.processors.hadoop.exception.RecordReaderFactoryException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.apache.nifi.serialization.RecordReader;
@@ -69,7 +70,6 @@ import org.apache.nifi.util.hive.HiveConfigurator;
import org.apache.nifi.util.hive.HiveOptions;
import org.apache.nifi.util.hive.ValidationResources;
-import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivilegedAction;
@@ -684,7 +684,7 @@ public class PutHive3Streaming extends AbstractProcessor {
try {
getLogger().debug("checking TGT on kerberosUser [{}]", new
Object[]{kerberosUser});
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Unable to relogin with kerberos
credentials for " + kerberosUser.getPrincipal(), e);
}
} else {
diff --git
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive_1_1-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive_1_1ConnectionPool.java
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive_1_1-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive_1_1ConnectionPool.java
index ebd0942..26116aa 100644
---
a/nifi-nar-bundles/nifi-hive-bundle/nifi-hive_1_1-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive_1_1ConnectionPool.java
+++
b/nifi-nar-bundles/nifi-hive-bundle/nifi-hive_1_1-processors/src/main/java/org/apache/nifi/dbcp/hive/Hive_1_1ConnectionPool.java
@@ -44,13 +44,13 @@ import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.apache.nifi.util.hive.AuthenticationFailedException;
import org.apache.nifi.util.hive.HiveConfigurator;
import org.apache.nifi.util.hive.ValidationResources;
-import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.PrivilegedExceptionAction;
@@ -403,7 +403,7 @@ public class Hive_1_1ConnectionPool extends
AbstractControllerService implements
try {
getLogger().debug("checking TGT on kerberosUser " +
kerberosUser);
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Unable to relogin with
kerberos credentials for " + kerberosUser.getPrincipal(), e);
}
} else {
diff --git
a/nifi-nar-bundles/nifi-kudu-bundle/nifi-kudu-processors/src/main/java/org/apache/nifi/processors/kudu/AbstractKuduProcessor.java
b/nifi-nar-bundles/nifi-kudu-bundle/nifi-kudu-processors/src/main/java/org/apache/nifi/processors/kudu/AbstractKuduProcessor.java
index 8724254..4131d2f 100644
---
a/nifi-nar-bundles/nifi-kudu-bundle/nifi-kudu-processors/src/main/java/org/apache/nifi/processors/kudu/AbstractKuduProcessor.java
+++
b/nifi-nar-bundles/nifi-kudu-bundle/nifi-kudu-processors/src/main/java/org/apache/nifi/processors/kudu/AbstractKuduProcessor.java
@@ -263,7 +263,7 @@ public abstract class AbstractKuduProcessor extends
AbstractProcessor {
protected KerberosUser createKerberosKeytabUser(String principal, String
keytab, ProcessContext context) {
return new KerberosKeytabUser(principal, keytab) {
@Override
- public synchronized void login() throws LoginException {
+ public synchronized void login() {
if (!isLoggedIn()) {
super.login();
@@ -276,7 +276,7 @@ public abstract class AbstractKuduProcessor extends
AbstractProcessor {
protected KerberosUser createKerberosPasswordUser(String principal, String
password, ProcessContext context) {
return new KerberosPasswordUser(principal, password) {
@Override
- public synchronized void login() throws LoginException {
+ public synchronized void login() {
if (!isLoggedIn()) {
super.login();
diff --git
a/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/main/java/org/apache/nifi/processors/solr/SolrProcessor.java
b/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/main/java/org/apache/nifi/processors/solr/SolrProcessor.java
index 332bf12..e9d440b 100644
---
a/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/main/java/org/apache/nifi/processors/solr/SolrProcessor.java
+++
b/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/main/java/org/apache/nifi/processors/solr/SolrProcessor.java
@@ -29,13 +29,13 @@ import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.security.krb.KerberosAction;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.apache.nifi.security.krb.KerberosKeytabUser;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.solr.client.solrj.SolrClient;
-import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
@@ -113,7 +113,7 @@ public abstract class SolrProcessor extends
AbstractProcessor {
try {
kerberosUser.logout();
kerberosUser = null;
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
getLogger().debug("Error logging out keytab user", e);
}
}
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
b/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
index b43f691..945412d 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
@@ -42,6 +42,7 @@ import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosAction;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
@@ -413,7 +414,7 @@ public class DBCPConnectionPool extends
AbstractControllerService implements DBC
if (kerberosUser != null) {
try {
kerberosUser.login();
- } catch (LoginException e) {
+ } catch (KerberosLoginException e) {
throw new InitializationException("Unable to authenticate
Kerberos principal", e);
}
}
@@ -530,7 +531,7 @@ public class DBCPConnectionPool extends
AbstractControllerService implements DBC
try {
getLogger().info("Error getting connection, performing
Kerberos re-login");
kerberosUser.login();
- } catch (LoginException le) {
+ } catch (KerberosLoginException le) {
throw new ProcessException("Unable to authenticate
Kerberos principal", le);
}
}
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/groovy/org/apache/nifi/dbcp/GroovyDBCPServiceTest.groovy
b/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/groovy/org/apache/nifi/dbcp/GroovyDBCPServiceTest.groovy
index cb267db..4d27530 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/groovy/org/apache/nifi/dbcp/GroovyDBCPServiceTest.groovy
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/groovy/org/apache/nifi/dbcp/GroovyDBCPServiceTest.groovy
@@ -19,13 +19,13 @@ package org.apache.nifi.dbcp
import org.apache.commons.dbcp2.BasicDataSource
import org.apache.nifi.reporting.InitializationException
import org.apache.nifi.security.krb.KerberosKeytabUser
+import org.apache.nifi.security.krb.KerberosLoginException
import org.apache.nifi.util.TestRunner
import org.apache.nifi.util.TestRunners
import org.junit.Assert
import org.junit.BeforeClass
import org.junit.Test
-import javax.security.auth.login.LoginException
import java.sql.Connection
import java.sql.SQLException
@@ -76,7 +76,7 @@ class GroovyDBCPServiceTest {
}
}
- @Test(expected = LoginException)
+ @Test(expected = KerberosLoginException)
void testDatasourceCloseSuccessWithKerberosUserLogoutException() {
final DBCPConnectionPool dbcpConnectionPoolService = new
DBCPConnectionPool()
@@ -84,8 +84,8 @@ class GroovyDBCPServiceTest {
dbcpConnectionPoolService.dataSource = basicDataSource
def kerberosKeytabUser = new KerberosKeytabUser("[email protected]",
"fake.keytab") {
@Override
- void logout() throws LoginException {
- throw new LoginException("fake logout exception")
+ void logout() {
+ throw new KerberosLoginException("fake logout exception")
}
}
dbcpConnectionPoolService.kerberosUser = kerberosKeytabUser
@@ -104,7 +104,7 @@ class GroovyDBCPServiceTest {
dbcpConnectionPoolService.dataSource = basicDataSource
def kerberosKeytabUser = new KerberosKeytabUser("[email protected]",
"fake.keytab") {
@Override
- void logout() throws LoginException {
+ void logout() {
}
}
dbcpConnectionPoolService.kerberosUser = kerberosKeytabUser
@@ -122,8 +122,8 @@ class GroovyDBCPServiceTest {
dbcpConnectionPoolService.dataSource = basicDataSource
def kerberosKeytabUser = new KerberosKeytabUser("[email protected]",
"fake.keytab") {
@Override
- void logout() throws LoginException {
- throw new LoginException("fake logout exception")
+ void logout() {
+ throw new KerberosLoginException("fake logout exception")
}
}
dbcpConnectionPoolService.kerberosUser = kerberosKeytabUser
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hadoop-dbcp-service-bundle/nifi-hadoop-dbcp-service/src/main/java/org/apache/nifi/dbcp/HadoopDBCPConnectionPool.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hadoop-dbcp-service-bundle/nifi-hadoop-dbcp-service/src/main/java/org/apache/nifi/dbcp/HadoopDBCPConnectionPool.java
index 7bdd631..614d5f8 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hadoop-dbcp-service-bundle/nifi-hadoop-dbcp-service/src/main/java/org/apache/nifi/dbcp/HadoopDBCPConnectionPool.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hadoop-dbcp-service-bundle/nifi-hadoop-dbcp-service/src/main/java/org/apache/nifi/dbcp/HadoopDBCPConnectionPool.java
@@ -44,6 +44,7 @@ import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
@@ -529,7 +530,7 @@ public class HadoopDBCPConnectionPool extends
AbstractControllerService implemen
* no exception while closing open connections
*/
@OnDisabled
- public void shutdown() throws SQLException, LoginException {
+ public void shutdown() throws SQLException {
try {
if (kerberosUser != null) {
kerberosUser.logout();
@@ -562,7 +563,7 @@ public class HadoopDBCPConnectionPool extends
AbstractControllerService implemen
try {
getLogger().debug("checking TGT on kerberosUser " +
kerberosUser);
kerberosUser.checkTGTAndRelogin();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException e) {
throw new ProcessException("Unable to relogin with
kerberos credentials for " + kerberosUser.getPrincipal(), e);
}
} else {
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/pom.xml
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/pom.xml
index 1374977..af692dc 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/pom.xml
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/pom.xml
@@ -62,7 +62,6 @@
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-distributed-cache-client-service-api</artifactId>
- <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
@@ -72,7 +71,10 @@
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-kerberos-credentials-service-api</artifactId>
- <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-kerberos-user-service-api</artifactId>
</dependency>
<dependency>
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_1_1_2_ClientService.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_1_1_2_ClientService.java
index d02c2b5..bd029c8 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_1_1_2_ClientService.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_1_1_2_ClientService.java
@@ -63,6 +63,7 @@ import org.apache.nifi.hbase.scan.Column;
import org.apache.nifi.hbase.scan.ResultCell;
import org.apache.nifi.hbase.scan.ResultHandler;
import org.apache.nifi.kerberos.KerberosCredentialsService;
+import org.apache.nifi.kerberos.KerberosUserService;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
@@ -106,6 +107,14 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
.required(false)
.build();
+ static final PropertyDescriptor KERBEROS_USER_SERVICE = new
PropertyDescriptor.Builder()
+ .name("kerberos-user-service")
+ .displayName("Kerberos User Service")
+ .description("Specifies the Kerberos User Controller Service that
should be used for authenticating with Kerberos")
+ .identifiesControllerService(KerberosUserService.class)
+ .required(false)
+ .build();
+
static final PropertyDescriptor HADOOP_CONF_FILES = new
PropertyDescriptor.Builder()
.name("Hadoop Configuration Files")
.description("Comma-separated list of Hadoop Configuration files," +
@@ -184,6 +193,7 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
List<PropertyDescriptor> props = new ArrayList<>();
props.add(HADOOP_CONF_FILES);
+ props.add(KERBEROS_USER_SERVICE);
props.add(KERBEROS_CREDENTIALS_SERVICE);
props.add(kerberosProperties.getKerberosPrincipal());
props.add(kerberosProperties.getKerberosKeytab());
@@ -232,6 +242,7 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
final String explicitKeytab =
validationContext.getProperty(kerberosProperties.getKerberosKeytab()).evaluateAttributeExpressions().getValue();
final String explicitPassword =
validationContext.getProperty(kerberosProperties.getKerberosPassword()).getValue();
final KerberosCredentialsService credentialsService =
validationContext.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
+ final KerberosUserService kerberosUserService =
validationContext.getProperty(KERBEROS_USER_SERVICE).asControllerService(KerberosUserService.class);
final String resolvedPrincipal;
final String resolvedKeytab;
@@ -267,9 +278,15 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
}
final Configuration hbaseConfig = resources.getConfiguration();
-
-
problems.addAll(KerberosProperties.validatePrincipalWithKeytabOrPassword(getClass().getSimpleName(),
hbaseConfig,
- resolvedPrincipal, resolvedKeytab, explicitPassword,
getLogger()));
+ if (kerberosUserService == null) {
+
problems.addAll(KerberosProperties.validatePrincipalWithKeytabOrPassword(getClass().getSimpleName(),
hbaseConfig,
+ resolvedPrincipal, resolvedKeytab, explicitPassword,
getLogger()));
+ } else {
+ final boolean securityEnabled =
SecurityUtil.isSecurityEnabled(hbaseConfig);
+ if (!securityEnabled) {
+ getLogger().warn("Hadoop Configuration does not have
security enabled, KerberosUserService will be ignored");
+ }
+ }
}
if (credentialsService != null && (explicitPrincipal != null ||
explicitKeytab != null || explicitPassword != null)) {
@@ -280,6 +297,22 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
.build());
}
+ if (kerberosUserService != null && (explicitPrincipal != null ||
explicitKeytab != null || explicitPassword != null)) {
+ problems.add(new ValidationResult.Builder()
+ .subject("Kerberos User")
+ .valid(false)
+ .explanation("Cannot specify a Kerberos User Service while
also specifying a Kerberos Principal, Kerberos Keytab, or Kerberos Password")
+ .build());
+ }
+
+ if (kerberosUserService != null && credentialsService != null) {
+ problems.add(new ValidationResult.Builder()
+ .subject("Kerberos User")
+ .valid(false)
+ .explanation("Cannot specify a Kerberos User Service while
also specifying a Kerberos Credentials Service")
+ .build());
+ }
+
if (!isAllowExplicitKeytab() && explicitKeytab != null) {
problems.add(new ValidationResult.Builder()
.subject("Kerberos Credentials")
@@ -359,43 +392,45 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
}
if (SecurityUtil.isSecurityEnabled(hbaseConfig)) {
- String principal =
context.getProperty(kerberosProperties.getKerberosPrincipal()).evaluateAttributeExpressions().getValue();
- String keyTab =
context.getProperty(kerberosProperties.getKerberosKeytab()).evaluateAttributeExpressions().getValue();
- String password =
context.getProperty(kerberosProperties.getKerberosPassword()).getValue();
-
- // If the Kerberos Credentials Service is specified, we need to
use its configuration, not the explicit properties for principal/keytab.
- // The customValidate method ensures that only one can be set, so
we know that the principal & keytab above are null.
- final KerberosCredentialsService credentialsService =
context.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
- if (credentialsService != null) {
- principal = credentialsService.getPrincipal();
- keyTab = credentialsService.getKeytab();
- }
+ getLogger().debug("HBase Security Enabled, creating KerberosUser");
+ final KerberosUser kerberosUser = createKerberosUser(context);
+ ugi = SecurityUtil.getUgiForKerberosUser(hbaseConfig,
kerberosUser);
+ kerberosUserReference.set(kerberosUser);
+ getLogger().info("Successfully logged in as principal {}",
kerberosUser.getPrincipal());
+ return getUgi().doAs((PrivilegedExceptionAction<Connection>)() ->
ConnectionFactory.createConnection(hbaseConfig));
+ } else {
+ getLogger().debug("Simple Authentication");
+ return ConnectionFactory.createConnection(hbaseConfig);
+ }
+ }
- if (keyTab != null) {
- kerberosUserReference.set(new KerberosKeytabUser(principal,
keyTab));
- getLogger().info("HBase Security Enabled, logging in as
principal {} with keytab {}", new Object[] {principal, keyTab});
- } else if (password != null) {
- kerberosUserReference.set(new KerberosPasswordUser(principal,
password));
- getLogger().info("HBase Security Enabled, logging in as
principal {} with password", new Object[] {principal});
- } else {
- throw new IOException("Unable to authenticate with Kerberos,
no keytab or password was provided");
- }
+ protected KerberosUser createKerberosUser(final ConfigurationContext
context) {
+ // Check Kerberos User Service first, if present then get the
KerberosUser from the service
+ // The customValidate method ensures that KerberosUserService can't be
set at the same time as the credentials service or explicit properties
+ final KerberosUserService kerberosUserService =
context.getProperty(KERBEROS_USER_SERVICE).asControllerService(KerberosUserService.class);
+ if (kerberosUserService != null) {
+ return kerberosUserService.createKerberosUser();
+ }
- ugi = SecurityUtil.getUgiForKerberosUser(hbaseConfig,
kerberosUserReference.get());
- getLogger().info("Successfully logged in as principal " +
principal);
+ String principal =
context.getProperty(kerberosProperties.getKerberosPrincipal()).evaluateAttributeExpressions().getValue();
+ String keyTab =
context.getProperty(kerberosProperties.getKerberosKeytab()).evaluateAttributeExpressions().getValue();
+ String password =
context.getProperty(kerberosProperties.getKerberosPassword()).getValue();
- return getUgi().doAs(new PrivilegedExceptionAction<Connection>() {
- @Override
- public Connection run() throws Exception {
- return ConnectionFactory.createConnection(hbaseConfig);
- }
- });
+ // If the Kerberos Credentials Service is specified, we need to use
its configuration, not the explicit properties for principal/keytab.
+ // The customValidate method ensures that only one can be set, so we
know that the principal & keytab above are null.
+ final KerberosCredentialsService credentialsService =
context.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
+ if (credentialsService != null) {
+ principal = credentialsService.getPrincipal();
+ keyTab = credentialsService.getKeytab();
+ }
+ if (keyTab != null) {
+ return new KerberosKeytabUser(principal, keyTab);
+ } else if (password != null) {
+ return new KerberosPasswordUser(principal, password);
} else {
- getLogger().info("Simple Authentication");
- return ConnectionFactory.createConnection(hbaseConfig);
+ throw new IllegalStateException("Unable to authenticate with
Kerberos, no keytab or password was provided");
}
-
}
protected Configuration getConfigurationFromFiles(final String
configFiles) {
@@ -417,6 +452,18 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
getLogger().warn("Failed to close connection to HBase due to
{}", new Object[]{ioe});
}
}
+
+ final KerberosUser kerberosUser = kerberosUserReference.get();
+ if (kerberosUser != null) {
+ try {
+ kerberosUser.logout();
+ } catch (final Exception e) {
+ getLogger().warn("Error logging out KerberosUser: {}",
e.getMessage(), e);
+ } finally {
+ ugi = null;
+ kerberosUserReference.set(null);
+ }
+ }
}
protected List<Put> buildPuts(byte[] rowKey, List<PutColumn> columns) {
@@ -890,6 +937,8 @@ public class HBase_1_1_2_ClientService extends
AbstractControllerService impleme
}
UserGroupInformation getUgi() {
+ getLogger().trace("getting UGI instance");
+ // if there is a KerberosUser associated with UGI, call
checkTGTAndRelogin to ensure UGI's underlying Subject has a valid ticket
SecurityUtil.checkTGTAndRelogin(getLogger(),
kerberosUserReference.get());
return ugi;
}
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_1_1_2_ClientService.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_1_1_2_ClientService.java
index 56b259c..4467538 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_1_1_2_ClientService.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_1_1_2-client-service-bundle/nifi-hbase_1_1_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_1_1_2_ClientService.java
@@ -26,6 +26,8 @@ import org.apache.nifi.hbase.put.PutFlowFile;
import org.apache.nifi.hbase.scan.Column;
import org.apache.nifi.hbase.scan.ResultCell;
import org.apache.nifi.hbase.scan.ResultHandler;
+import org.apache.nifi.kerberos.KerberosCredentialsService;
+import org.apache.nifi.kerberos.KerberosUserService;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
@@ -49,6 +51,7 @@ import java.util.NavigableMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -178,6 +181,81 @@ public class TestHBase_1_1_2_ClientService {
runner.setProperty(service,
kerberosPropsWithoutFile.getKerberosKeytab(), "src/test/resources/fake.keytab");
runner.setProperty(service,
kerberosPropsWithoutFile.getKerberosPrincipal(), "test@REALM");
runner.assertNotValid(service);
+
+ // Kerberos - add valid options with password
+ service = new MockHBaseClientService(table, COL_FAM,
kerberosPropsWithFile, true);
+ runner.addControllerService("hbaseClientService", service);
+ runner.setProperty(service,
HBase_1_1_2_ClientService.HADOOP_CONF_FILES,
+ "src/test/resources/hbase-site.xml,
src/test/resources/core-site-security.xml");
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPassword(), "password");
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPrincipal(), "test@REALM");
+ runner.assertValid(service);
+
+ // Kerberos - keytab and password at same time should be invalid
+ runner.setProperty(service, kerberosPropsWithFile.getKerberosKeytab(),
"src/test/resources/fake.keytab");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosKeytab());
+ runner.assertValid(service);
+
+ // Kerberos - credentials service not valid when other kerberos
properties set
+ final KerberosCredentialsService credentialsService =
enabledKerberosCredentialsService(runner);
+ runner.setProperty(service,
HBase_1_1_2_ClientService.KERBEROS_CREDENTIALS_SERVICE,
credentialsService.getIdentifier());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPassword());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPrincipal());
+ runner.assertValid(service);
+
+ runner.setProperty(service, kerberosPropsWithFile.getKerberosKeytab(),
"src/test/resources/fake.keytab");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosKeytab());
+ runner.assertValid(service);
+
+ // Kerberos - user service with credentials service is invalid
+ final KerberosUserService userService =
enableKerberosUserService(runner);
+ runner.setProperty(service,
HBase_1_1_2_ClientService.KERBEROS_USER_SERVICE, userService.getIdentifier());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
HBase_1_1_2_ClientService.KERBEROS_CREDENTIALS_SERVICE);
+ runner.assertValid(service);
+
+ // Kerberos - user service with other kerberos properties is invalid
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPassword(), "password");
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPrincipal(), "test@REALM");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPassword());
+ runner.setProperty(service, kerberosPropsWithFile.getKerberosKeytab(),
"src/test/resources/fake.keytab");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosKeytab());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPrincipal());
+ runner.assertValid(service);
+ }
+
+ private KerberosUserService enableKerberosUserService(final TestRunner
runner) throws InitializationException {
+ final KerberosUserService kerberosUserService =
mock(KerberosUserService.class);
+ when(kerberosUserService.getIdentifier()).thenReturn("userService1");
+ runner.addControllerService(kerberosUserService.getIdentifier(),
kerberosUserService);
+ runner.enableControllerService(kerberosUserService);
+ return kerberosUserService;
+ }
+
+ private KerberosCredentialsService enabledKerberosCredentialsService(final
TestRunner runner) throws InitializationException {
+ final KerberosCredentialsService credentialsService =
mock(KerberosCredentialsService.class);
+ when(credentialsService.getIdentifier()).thenReturn("credsService1");
+ when(credentialsService.getPrincipal()).thenReturn("principal1");
+ when(credentialsService.getKeytab()).thenReturn("keytab1");
+
+ runner.addControllerService(credentialsService.getIdentifier(),
credentialsService);
+ runner.enableControllerService(credentialsService);
+ return credentialsService;
}
@Test
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/pom.xml
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/pom.xml
index 8048593..2649c81 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/pom.xml
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/pom.xml
@@ -60,17 +60,18 @@
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-distributed-cache-client-service-api</artifactId>
- <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-record</artifactId>
- <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-kerberos-credentials-service-api</artifactId>
- <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-kerberos-user-service-api</artifactId>
</dependency>
<dependency>
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_2_ClientService.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_2_ClientService.java
index 1929de9..d1797d4 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_2_ClientService.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/main/java/org/apache/nifi/hbase/HBase_2_ClientService.java
@@ -63,6 +63,7 @@ import org.apache.nifi.hbase.scan.Column;
import org.apache.nifi.hbase.scan.ResultCell;
import org.apache.nifi.hbase.scan.ResultHandler;
import org.apache.nifi.kerberos.KerberosCredentialsService;
+import org.apache.nifi.kerberos.KerberosUserService;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.krb.KerberosKeytabUser;
@@ -105,6 +106,14 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
.required(false)
.build();
+ static final PropertyDescriptor KERBEROS_USER_SERVICE = new
PropertyDescriptor.Builder()
+ .name("kerberos-user-service")
+ .displayName("Kerberos User Service")
+ .description("Specifies the Kerberos User Controller Service that
should be used for authenticating with Kerberos")
+ .identifiesControllerService(KerberosUserService.class)
+ .required(false)
+ .build();
+
static final PropertyDescriptor HADOOP_CONF_FILES = new
PropertyDescriptor.Builder()
.name("Hadoop Configuration Files")
.description("Comma-separated list of Hadoop Configuration files," +
@@ -184,6 +193,7 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
List<PropertyDescriptor> props = new ArrayList<>();
props.add(HADOOP_CONF_FILES);
+ props.add(KERBEROS_USER_SERVICE);
props.add(KERBEROS_CREDENTIALS_SERVICE);
props.add(kerberosProperties.getKerberosPrincipal());
props.add(kerberosProperties.getKerberosKeytab());
@@ -232,6 +242,7 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
final String explicitKeytab =
validationContext.getProperty(kerberosProperties.getKerberosKeytab()).evaluateAttributeExpressions().getValue();
final String explicitPassword =
validationContext.getProperty(kerberosProperties.getKerberosPassword()).getValue();
final KerberosCredentialsService credentialsService =
validationContext.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
+ final KerberosUserService kerberosUserService =
validationContext.getProperty(KERBEROS_USER_SERVICE).asControllerService(KerberosUserService.class);
final String resolvedPrincipal;
final String resolvedKeytab;
@@ -267,9 +278,15 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
}
final Configuration hbaseConfig = resources.getConfiguration();
-
-
problems.addAll(KerberosProperties.validatePrincipalWithKeytabOrPassword(getClass().getSimpleName(),
hbaseConfig,
- resolvedPrincipal, resolvedKeytab, explicitPassword,
getLogger()));
+ if (kerberosUserService == null) {
+
problems.addAll(KerberosProperties.validatePrincipalWithKeytabOrPassword(getClass().getSimpleName(),
hbaseConfig,
+ resolvedPrincipal, resolvedKeytab, explicitPassword,
getLogger()));
+ } else {
+ final boolean securityEnabled =
SecurityUtil.isSecurityEnabled(hbaseConfig);
+ if (!securityEnabled) {
+ getLogger().warn("Hadoop Configuration does not have
security enabled, KerberosUserService will be ignored");
+ }
+ }
}
if (credentialsService != null && (explicitPrincipal != null ||
explicitKeytab != null || explicitPassword != null)) {
@@ -280,6 +297,22 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
.build());
}
+ if (kerberosUserService != null && (explicitPrincipal != null ||
explicitKeytab != null || explicitPassword != null)) {
+ problems.add(new ValidationResult.Builder()
+ .subject("Kerberos User")
+ .valid(false)
+ .explanation("Cannot specify a Kerberos User Service while
also specifying a Kerberos Principal, Kerberos Keytab, or Kerberos Password")
+ .build());
+ }
+
+ if (kerberosUserService != null && credentialsService != null) {
+ problems.add(new ValidationResult.Builder()
+ .subject("Kerberos User")
+ .valid(false)
+ .explanation("Cannot specify a Kerberos User Service while
also specifying a Kerberos Credentials Service")
+ .build());
+ }
+
if (!isAllowExplicitKeytab() && explicitKeytab != null) {
problems.add(new ValidationResult.Builder()
.subject("Kerberos Credentials")
@@ -359,43 +392,45 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
}
if (SecurityUtil.isSecurityEnabled(hbaseConfig)) {
- String principal =
context.getProperty(kerberosProperties.getKerberosPrincipal()).evaluateAttributeExpressions().getValue();
- String keyTab =
context.getProperty(kerberosProperties.getKerberosKeytab()).evaluateAttributeExpressions().getValue();
- String password =
context.getProperty(kerberosProperties.getKerberosPassword()).getValue();
-
- // If the Kerberos Credentials Service is specified, we need to
use its configuration, not the explicit properties for principal/keytab.
- // The customValidate method ensures that only one can be set, so
we know that the principal & keytab above are null.
- final KerberosCredentialsService credentialsService =
context.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
- if (credentialsService != null) {
- principal = credentialsService.getPrincipal();
- keyTab = credentialsService.getKeytab();
- }
+ getLogger().debug("HBase Security Enabled, creating KerberosUser");
+ final KerberosUser kerberosUser = createKerberosUser(context);
+ ugi = SecurityUtil.getUgiForKerberosUser(hbaseConfig,
kerberosUser);
+ kerberosUserReference.set(kerberosUser);
+ getLogger().info("Successfully logged in as principal {}",
kerberosUser.getPrincipal());
+ return getUgi().doAs((PrivilegedExceptionAction<Connection>)() ->
ConnectionFactory.createConnection(hbaseConfig));
+ } else {
+ getLogger().debug("Simple Authentication");
+ return ConnectionFactory.createConnection(hbaseConfig);
+ }
+ }
- if (keyTab != null) {
- kerberosUserReference.set(new KerberosKeytabUser(principal,
keyTab));
- getLogger().info("HBase Security Enabled, logging in as
principal {} with keytab {}", new Object[] {principal, keyTab});
- } else if (password != null) {
- kerberosUserReference.set(new KerberosPasswordUser(principal,
password));
- getLogger().info("HBase Security Enabled, logging in as
principal {} with password", new Object[] {principal});
- } else {
- throw new IOException("Unable to authenticate with Kerberos,
no keytab or password was provided");
- }
+ protected KerberosUser createKerberosUser(final ConfigurationContext
context) {
+ // Check Kerberos User Service first, if present then get the
KerberosUser from the service
+ // The customValidate method ensures that KerberosUserService can't be
set at the same time as the credentials service or explicit properties
+ final KerberosUserService kerberosUserService =
context.getProperty(KERBEROS_USER_SERVICE).asControllerService(KerberosUserService.class);
+ if (kerberosUserService != null) {
+ return kerberosUserService.createKerberosUser();
+ }
- ugi = SecurityUtil.getUgiForKerberosUser(hbaseConfig,
kerberosUserReference.get());
- getLogger().info("Successfully logged in as principal " +
principal);
+ String principal =
context.getProperty(kerberosProperties.getKerberosPrincipal()).evaluateAttributeExpressions().getValue();
+ String keyTab =
context.getProperty(kerberosProperties.getKerberosKeytab()).evaluateAttributeExpressions().getValue();
+ String password =
context.getProperty(kerberosProperties.getKerberosPassword()).getValue();
- return getUgi().doAs(new PrivilegedExceptionAction<Connection>() {
- @Override
- public Connection run() throws Exception {
- return ConnectionFactory.createConnection(hbaseConfig);
- }
- });
+ // If the Kerberos Credentials Service is specified, we need to use
its configuration, not the explicit properties for principal/keytab.
+ // The customValidate method ensures that only one can be set, so we
know that the principal & keytab above are null.
+ final KerberosCredentialsService credentialsService =
context.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
+ if (credentialsService != null) {
+ principal = credentialsService.getPrincipal();
+ keyTab = credentialsService.getKeytab();
+ }
+ if (keyTab != null) {
+ return new KerberosKeytabUser(principal, keyTab);
+ } else if (password != null) {
+ return new KerberosPasswordUser(principal, password);
} else {
- getLogger().info("Simple Authentication");
- return ConnectionFactory.createConnection(hbaseConfig);
+ throw new IllegalStateException("Unable to authenticate with
Kerberos, no keytab or password was provided");
}
-
}
protected Configuration getConfigurationFromFiles(final String
configFiles) {
@@ -413,8 +448,20 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
if (connection != null) {
try {
connection.close();
- } catch (final IOException ioe) {
- getLogger().warn("Failed to close connection to HBase due to
{}", new Object[]{ioe});
+ } catch (final Exception e) {
+ getLogger().warn("HBase connection close failed", e);
+ }
+ }
+
+ final KerberosUser kerberosUser = kerberosUserReference.get();
+ if (kerberosUser != null) {
+ try {
+ kerberosUser.logout();
+ } catch (final Exception e) {
+ getLogger().warn("KeberosUser Logout Failed", e);
+ } finally {
+ ugi = null;
+ kerberosUserReference.set(null);
}
}
}
@@ -891,6 +938,8 @@ public class HBase_2_ClientService extends
AbstractControllerService implements
}
UserGroupInformation getUgi() throws IOException {
+ getLogger().trace("getting UGI instance");
+ // if there is a KerberosUser associated with UGI, call
checkTGTAndRelogin to ensure UGI's underlying Subject has a valid ticket
SecurityUtil.checkTGTAndRelogin(getLogger(),
kerberosUserReference.get());
return ugi;
}
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_2_ClientService.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_2_ClientService.java
index e27a90c..1eb7b48 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_2_ClientService.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hbase_2-client-service-bundle/nifi-hbase_2-client-service/src/test/java/org/apache/nifi/hbase/TestHBase_2_ClientService.java
@@ -26,6 +26,8 @@ import org.apache.nifi.hbase.put.PutFlowFile;
import org.apache.nifi.hbase.scan.Column;
import org.apache.nifi.hbase.scan.ResultCell;
import org.apache.nifi.hbase.scan.ResultHandler;
+import org.apache.nifi.kerberos.KerberosCredentialsService;
+import org.apache.nifi.kerberos.KerberosUserService;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
@@ -49,6 +51,7 @@ import java.util.NavigableMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -178,6 +181,81 @@ public class TestHBase_2_ClientService {
runner.setProperty(service,
kerberosPropsWithoutFile.getKerberosKeytab(), "src/test/resources/fake.keytab");
runner.setProperty(service,
kerberosPropsWithoutFile.getKerberosPrincipal(), "test@REALM");
runner.assertNotValid(service);
+
+ // Kerberos - add valid options with password
+ service = new MockHBaseClientService(table, COL_FAM,
kerberosPropsWithFile, true);
+ runner.addControllerService("hbaseClientService", service);
+ runner.setProperty(service, HBase_2_ClientService.HADOOP_CONF_FILES,
+ "src/test/resources/hbase-site.xml,
src/test/resources/core-site-security.xml");
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPassword(), "password");
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPrincipal(), "test@REALM");
+ runner.assertValid(service);
+
+ // Kerberos - keytab and password at same time should be invalid
+ runner.setProperty(service, kerberosPropsWithFile.getKerberosKeytab(),
"src/test/resources/fake.keytab");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosKeytab());
+ runner.assertValid(service);
+
+ // Kerberos - credentials service not valid when other kerberos
properties set
+ final KerberosCredentialsService credentialsService =
enabledKerberosCredentialsService(runner);
+ runner.setProperty(service,
HBase_2_ClientService.KERBEROS_CREDENTIALS_SERVICE,
credentialsService.getIdentifier());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPassword());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPrincipal());
+ runner.assertValid(service);
+
+ runner.setProperty(service, kerberosPropsWithFile.getKerberosKeytab(),
"src/test/resources/fake.keytab");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosKeytab());
+ runner.assertValid(service);
+
+ // Kerberos - user service with credentials service is invalid
+ final KerberosUserService userService =
enableKerberosUserService(runner);
+ runner.setProperty(service,
HBase_2_ClientService.KERBEROS_USER_SERVICE, userService.getIdentifier());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
HBase_2_ClientService.KERBEROS_CREDENTIALS_SERVICE);
+ runner.assertValid(service);
+
+ // Kerberos - user service with other kerberos properties is invalid
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPassword(), "password");
+ runner.setProperty(service,
kerberosPropsWithFile.getKerberosPrincipal(), "test@REALM");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPassword());
+ runner.setProperty(service, kerberosPropsWithFile.getKerberosKeytab(),
"src/test/resources/fake.keytab");
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosKeytab());
+ runner.assertNotValid(service);
+
+ runner.removeProperty(service,
kerberosPropsWithFile.getKerberosPrincipal());
+ runner.assertValid(service);
+ }
+
+ private KerberosUserService enableKerberosUserService(final TestRunner
runner) throws InitializationException {
+ final KerberosUserService kerberosUserService =
mock(KerberosUserService.class);
+ when(kerberosUserService.getIdentifier()).thenReturn("userService1");
+ runner.addControllerService(kerberosUserService.getIdentifier(),
kerberosUserService);
+ runner.enableControllerService(kerberosUserService);
+ return kerberosUserService;
+ }
+
+ private KerberosCredentialsService enabledKerberosCredentialsService(final
TestRunner runner) throws InitializationException {
+ final KerberosCredentialsService credentialsService =
mock(KerberosCredentialsService.class);
+ when(credentialsService.getIdentifier()).thenReturn("credsService1");
+ when(credentialsService.getPrincipal()).thenReturn("principal1");
+ when(credentialsService.getKeytab()).thenReturn("keytab1");
+
+ runner.addControllerService(credentialsService.getIdentifier(),
credentialsService);
+ runner.enableControllerService(credentialsService);
+ return credentialsService;
}
@Test
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/KerberosUserLogin.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/KerberosUserLogin.java
index d73f348..aac8960 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/KerberosUserLogin.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/KerberosUserLogin.java
@@ -46,7 +46,7 @@ public class KerberosUserLogin implements Login {
}
@Override
- public LoginContext login() throws LoginException {
+ public LoginContext login() {
kerberosUser.login();
// the KerberosUser doesn't expose the LoginContext, but
SchemaRegistryClient doesn't use
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/SchemaRegistryClientWithKerberosPassword.java
b/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/SchemaRegistryClientWithKerberosPassword.java
index ca84f8f..18eb77c 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/SchemaRegistryClientWithKerberosPassword.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-hwx-schema-registry-bundle/nifi-hwx-schema-registry-service/src/main/java/org/apache/nifi/schemaregistry/hortonworks/SchemaRegistryClientWithKerberosPassword.java
@@ -18,6 +18,7 @@ package org.apache.nifi.schemaregistry.hortonworks;
import com.hortonworks.registries.schemaregistry.client.SchemaRegistryClient;
import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.security.krb.KerberosLoginException;
import org.apache.nifi.security.krb.KerberosPasswordUser;
import org.apache.nifi.security.krb.KerberosUser;
import org.slf4j.Logger;
@@ -70,7 +71,7 @@ public class SchemaRegistryClientWithKerberosPassword extends
SchemaRegistryClie
try {
login.login();
- } catch (LoginException e) {
+ } catch (final KerberosLoginException | LoginException e) {
LOGGER.error("Failed to login as principal `{}`", new
Object[]{principal}, e);
}
}