This is an automated email from the ASF dual-hosted git repository.

mattyb149 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/master by this push:
     new 2bbfb32  NIFI-5945 Add support for password login to kerberos code in 
nifi-security-utils
2bbfb32 is described below

commit 2bbfb3217be40abe4af7ddb8627808d12d99bb17
Author: Bryan Bende <bbe...@apache.org>
AuthorDate: Wed Jan 9 17:37:10 2019 -0500

    NIFI-5945 Add support for password login to kerberos code in 
nifi-security-utils
    
    Fixing solr test
    
    Signed-off-by: Matthew Burgess <mattyb...@apache.org>
    
    This closes #3256
---
 ...rdKeytabUser.java => AbstractKerberosUser.java} |  41 +++-----
 .../nifi/security/krb/ConfigurationUtil.java       |  25 +++++
 .../krb/{KeytabAction.java => KerberosAction.java} |  34 +++----
 .../nifi/security/krb/KerberosKeytabUser.java      |  59 +++++++++++
 .../nifi/security/krb/KerberosPasswordUser.java    | 110 +++++++++++++++++++++
 .../krb/{KeytabUser.java => KerberosUser.java}     |   7 +-
 .../nifi/security/krb/KeytabConfiguration.java     |   9 +-
 .../org/apache/nifi/security/krb/KDCServer.java    |   5 +-
 .../krb/{KeytabUserIT.java => KerberosUserIT.java} |  63 +++++++++---
 .../nifi/security/krb/TestKeytabConfiguration.java |   2 +-
 .../apache/nifi/processors/solr/SolrProcessor.java |  32 +++---
 .../processors/solr/TestPutSolrContentStream.java  |  45 ++++-----
 12 files changed, 320 insertions(+), 112 deletions(-)

diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/StandardKeytabUser.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
similarity index 86%
rename from 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/StandardKeytabUser.java
rename to 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
index 7302ee0..32eb9bb 100644
--- 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/StandardKeytabUser.java
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/AbstractKerberosUser.java
@@ -23,7 +23,6 @@ import org.slf4j.LoggerFactory;
 import javax.security.auth.Subject;
 import javax.security.auth.kerberos.KerberosPrincipal;
 import javax.security.auth.kerberos.KerberosTicket;
-import javax.security.auth.login.Configuration;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 import java.security.PrivilegedAction;
@@ -34,14 +33,9 @@ import java.util.Date;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-/**
- * Used to authenticate and execute actions when Kerberos is enabled and a 
keytab is being used.
- *
- * Some of the functionality in this class is adapted from Hadoop's 
UserGroupInformation.
- */
-public class StandardKeytabUser implements KeytabUser {
+public abstract class AbstractKerberosUser implements KerberosUser {
 
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(StandardKeytabUser.class);
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(AbstractKerberosUser.class);
 
     static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
 
@@ -50,18 +44,15 @@ public class StandardKeytabUser implements KeytabUser {
      */
     static final float TICKET_RENEW_WINDOW = 0.80f;
 
-    private final String principal;
-    private final String keytabFile;
-    private final AtomicBoolean loggedIn = new AtomicBoolean(false);
+    protected final String principal;
+    protected final AtomicBoolean loggedIn = new AtomicBoolean(false);
 
-    private Subject subject;
-    private LoginContext loginContext;
+    protected Subject subject;
+    protected LoginContext loginContext;
 
-    public StandardKeytabUser(final String principal, final String keytabFile) 
{
+    public AbstractKerberosUser(final String principal) {
         this.principal = principal;
-        this.keytabFile = keytabFile;
-        Validate.notBlank(principal);
-        Validate.notBlank(keytabFile);
+        Validate.notBlank(this.principal);
     }
 
     /**
@@ -80,19 +71,19 @@ public class StandardKeytabUser implements KeytabUser {
             if (loginContext == null) {
                 LOGGER.debug("Initializing new login context...");
                 this.subject = new Subject();
-
-                final Configuration config = new 
KeytabConfiguration(principal, keytabFile);
-                this.loginContext = new LoginContext("KeytabConf", subject, 
null, config);
+                this.loginContext = createLoginContext(subject);
             }
 
             loginContext.login();
             loggedIn.set(true);
             LOGGER.debug("Successful login for {}", new Object[]{principal});
         } catch (LoginException le) {
-            throw new LoginException("Unable to login with " + principal + " 
and " + keytabFile + " due to: " + le.getMessage());
+            throw new LoginException("Unable to login with " + principal + " 
due to: " + le.getMessage());
         }
     }
 
+    protected abstract LoginContext createLoginContext(final Subject subject) 
throws LoginException;
+
     /**
      * Performs a logout of the current user.
      *
@@ -244,14 +235,6 @@ public class StandardKeytabUser implements KeytabUser {
         return principal;
     }
 
-    /**
-     * @return the keytab file for this user
-     */
-    @Override
-    public String getKeytabFile() {
-        return keytabFile;
-    }
-
     // Visible for testing
     Subject getSubject() {
         return this.subject;
diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/ConfigurationUtil.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/ConfigurationUtil.java
new file mode 100644
index 0000000..131ff22
--- /dev/null
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/ConfigurationUtil.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+public interface ConfigurationUtil {
+
+    boolean IS_IBM = System.getProperty("java.vendor", "").contains("IBM");
+    String IBM_KRB5_LOGIN_MODULE = 
"com.ibm.security.auth.module.Krb5LoginModule";
+    String SUN_KRB5_LOGIN_MODULE = 
"com.sun.security.auth.module.Krb5LoginModule";
+
+}
diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabAction.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
similarity index 79%
rename from 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabAction.java
rename to 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
index 5e3f592..bd3e1f9 100644
--- 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabAction.java
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosAction.java
@@ -25,24 +25,24 @@ import javax.security.auth.login.LoginException;
 import java.security.PrivilegedAction;
 
 /**
- * Helper class for processors to perform an action as a KeytabUser.
+ * Helper class for processors to perform an action as a KerberosUser.
  */
-public class KeytabAction {
+public class KerberosAction {
 
-    private final KeytabUser keytabUser;
+    private final KerberosUser kerberosUser;
     private final PrivilegedAction action;
     private final ProcessContext context;
     private final ComponentLog logger;
 
-    public KeytabAction(final KeytabUser keytabUser,
-                        final PrivilegedAction action,
-                        final ProcessContext context,
-                        final ComponentLog logger) {
-        this.keytabUser = keytabUser;
+    public KerberosAction(final KerberosUser kerberosUser,
+                          final PrivilegedAction action,
+                          final ProcessContext context,
+                          final ComponentLog logger) {
+        this.kerberosUser = kerberosUser;
         this.action = action;
         this.context = context;
         this.logger = logger;
-        Validate.notNull(this.keytabUser);
+        Validate.notNull(this.kerberosUser);
         Validate.notNull(this.action);
         Validate.notNull(this.context);
         Validate.notNull(this.logger);
@@ -50,10 +50,10 @@ public class KeytabAction {
 
     public void execute() {
         // lazily login the first time the processor executes
-        if (!keytabUser.isLoggedIn()) {
+        if (!kerberosUser.isLoggedIn()) {
             try {
-                keytabUser.login();
-                logger.info("Successful login for {}", new 
Object[]{keytabUser.getPrincipal()});
+                kerberosUser.login();
+                logger.info("Successful login for {}", new 
Object[]{kerberosUser.getPrincipal()});
             } catch (LoginException e) {
                 // make sure to yield so the processor doesn't keep retrying 
the rolled back flow files immediately
                 context.yield();
@@ -63,7 +63,7 @@ public class KeytabAction {
 
         // check if we need to re-login, will only happen if re-login window 
is reached (80% of TGT life)
         try {
-            keytabUser.checkTGTAndRelogin();
+            kerberosUser.checkTGTAndRelogin();
         } catch (LoginException e) {
             // make sure to yield so the processor doesn't keep retrying the 
rolled back flow files immediately
             context.yield();
@@ -72,15 +72,15 @@ public class KeytabAction {
 
         // attempt to execute the action, if an exception is caught attempt to 
logout/login and retry
         try {
-            keytabUser.doAs(action);
+            kerberosUser.doAs(action);
         } catch (SecurityException se) {
             logger.info("Privileged action failed, attempting relogin and 
retrying...");
             logger.debug("", se);
 
             try {
-                keytabUser.logout();
-                keytabUser.login();
-                keytabUser.doAs(action);
+                kerberosUser.logout();
+                kerberosUser.login();
+                kerberosUser.doAs(action);
             } catch (Exception e) {
                 // make sure to yield so the processor doesn't keep retrying 
the rolled back flow files immediately
                 context.yield();
diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosKeytabUser.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosKeytabUser.java
new file mode 100644
index 0000000..a2af82e
--- /dev/null
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosKeytabUser.java
@@ -0,0 +1,59 @@
+/*
+ * 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;
+
+import org.apache.commons.lang3.Validate;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/**
+ * Used to authenticate and execute actions when Kerberos is enabled and a 
keytab is being used.
+ *
+ * Some of the functionality in this class is adapted from Hadoop's 
UserGroupInformation.
+ */
+public class KerberosKeytabUser extends AbstractKerberosUser {
+
+    private final String keytabFile;
+
+    public KerberosKeytabUser(final String principal, final String keytabFile) 
{
+        super(principal);
+        this.keytabFile = keytabFile;
+        Validate.notBlank(keytabFile);
+    }
+
+    @Override
+    protected LoginContext createLoginContext(Subject subject) throws 
LoginException {
+        final Configuration config = new KeytabConfiguration(principal, 
keytabFile);
+        return new LoginContext("KeytabConf", subject, null, config);
+    }
+
+    /**
+     * @return the keytab file for this user
+     */
+    public String getKeytabFile() {
+        return keytabFile;
+    }
+
+    // Visible for testing
+    Subject getSubject() {
+        return this.subject;
+    }
+
+}
diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosPasswordUser.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosPasswordUser.java
new file mode 100644
index 0000000..d81fc85
--- /dev/null
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosPasswordUser.java
@@ -0,0 +1,110 @@
+/*
+ * 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;
+
+import org.apache.commons.lang3.Validate;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.util.HashMap;
+
+/**
+ * KerberosUser that authenticates via username and password instead of keytab.
+ */
+public class KerberosPasswordUser extends AbstractKerberosUser {
+
+    private final String password;
+
+    public KerberosPasswordUser(final String principal, final String password) 
{
+        super(principal);
+        this.password = password;
+        Validate.notBlank(this.password);
+    }
+
+    @Override
+    protected LoginContext createLoginContext(final Subject subject) throws 
LoginException {
+        final Configuration configuration = new PasswordConfig();
+        final CallbackHandler callbackHandler = new 
UsernamePasswordCallbackHandler(principal, password);
+        return new LoginContext("PasswordConf", subject, callbackHandler, 
configuration);
+    }
+
+    /**
+     * JAAS Configuration to use when logging in with username/password.
+     */
+    private static class PasswordConfig extends Configuration {
+
+        @Override
+        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+            HashMap<String, String> options = new HashMap<String, String>();
+            options.put("storeKey", "true");
+            options.put("refreshKrb5Config", "true");
+
+            final String krbLoginModuleName = ConfigurationUtil.IS_IBM
+                    ? ConfigurationUtil.IBM_KRB5_LOGIN_MODULE : 
ConfigurationUtil.SUN_KRB5_LOGIN_MODULE;
+
+            return new AppConfigurationEntry[] {
+                    new AppConfigurationEntry(
+                            krbLoginModuleName,
+                            
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+                            options
+                    )
+            };
+        }
+
+    }
+
+    /**
+     * CallbackHandler that provides the given username and password.
+     */
+    private static class UsernamePasswordCallbackHandler implements 
CallbackHandler {
+
+        private final String username;
+        private final String password;
+
+        public UsernamePasswordCallbackHandler(final String username, final 
String password) {
+            this.username = username;
+            this.password = password;
+            Validate.notBlank(this.username);
+            Validate.notBlank(this.password);
+        }
+
+        public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
+            for (final Callback callback : callbacks) {
+                if (callback instanceof NameCallback) {
+                    final NameCallback nameCallback = (NameCallback) callback;
+                    nameCallback.setName(username);
+                } else if (callback instanceof PasswordCallback) {
+                    final PasswordCallback passwordCallback = 
(PasswordCallback) callback;
+                    passwordCallback.setPassword(password.toCharArray());
+                } else {
+                    throw new IllegalStateException("Unexpected callback type: 
" + callback.getClass().getCanonicalName());
+                }
+            }
+        }
+
+    }
+
+}
diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabUser.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
similarity index 95%
rename from 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabUser.java
rename to 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
index 42089c2..16e4fd2 100644
--- 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabUser.java
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KerberosUser.java
@@ -24,7 +24,7 @@ import java.security.PrivilegedExceptionAction;
 /**
  * A keytab-based user that can login/logout and perform actions as the given 
user.
  */
-public interface KeytabUser {
+public interface KerberosUser {
 
     /**
      * Performs a login for the given user.
@@ -80,9 +80,4 @@ public interface KeytabUser {
      */
     String getPrincipal();
 
-    /**
-     * @return the keytab file for this user
-     */
-    String getKeytabFile();
-
 }
diff --git 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabConfiguration.java
 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabConfiguration.java
index 0ad0efe..24af9b2 100644
--- 
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabConfiguration.java
+++ 
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/krb/KeytabConfiguration.java
@@ -28,10 +28,6 @@ import java.util.Map;
  */
 public class KeytabConfiguration extends Configuration {
 
-    static final boolean IS_IBM = System.getProperty("java.vendor", 
"").contains("IBM");
-    static final String IBM_KRB5_LOGIN_MODULE = 
"com.ibm.security.auth.module.Krb5LoginModule";
-    static final String SUN_KRB5_LOGIN_MODULE = 
"com.sun.security.auth.module.Krb5LoginModule";
-
     private final String principal;
     private final String keytabFile;
 
@@ -53,7 +49,7 @@ public class KeytabConfiguration extends Configuration {
         options.put("principal", principal);
         options.put("refreshKrb5Config", "true");
 
-        if (IS_IBM) {
+        if (ConfigurationUtil.IS_IBM) {
             options.put("useKeytab", keytabFile);
             options.put("credsType", "both");
         } else {
@@ -64,7 +60,8 @@ public class KeytabConfiguration extends Configuration {
             options.put("storeKey", "true");
         }
 
-        final String krbLoginModuleName = IS_IBM ? IBM_KRB5_LOGIN_MODULE : 
SUN_KRB5_LOGIN_MODULE;
+        final String krbLoginModuleName = ConfigurationUtil.IS_IBM
+                ? ConfigurationUtil.IBM_KRB5_LOGIN_MODULE : 
ConfigurationUtil.SUN_KRB5_LOGIN_MODULE;
 
         this.kerberosKeytabConfigEntry = new AppConfigurationEntry(
                 krbLoginModuleName, 
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
diff --git 
a/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KDCServer.java
 
b/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KDCServer.java
index 5669b07..478b4de 100644
--- 
a/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KDCServer.java
+++ 
b/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KDCServer.java
@@ -67,8 +67,11 @@ public class KDCServer {
         return kdc.getRealm();
     }
 
-    public void createKeytabFile(final File keytabFile, final String... names) 
throws Exception {
+    public void createKeytabPrincipal(final File keytabFile, final String... 
names) throws Exception {
         kdc.createPrincipal(keytabFile, names);
     }
 
+    public void createPasswordPrincipal(final String principal, final String 
password) throws Exception {
+        kdc.createPrincipal(principal, password);
+    }
 }
diff --git 
a/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KeytabUserIT.java
 
b/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KerberosUserIT.java
similarity index 65%
rename from 
nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KeytabUserIT.java
rename to 
nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KerberosUserIT.java
index 795f4fb..e636008 100644
--- 
a/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KeytabUserIT.java
+++ 
b/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/KerberosUserIT.java
@@ -37,7 +37,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 
-public class KeytabUserIT {
+public class KerberosUserIT {
 
     @ClassRule
     public static TemporaryFolder tmpDir = new TemporaryFolder();
@@ -50,6 +50,9 @@ public class KeytabUserIT {
     private static KerberosPrincipal principal2;
     private static File principal2KeytabFile;
 
+    private static KerberosPrincipal principal3;
+    private static final String principal3Password = "changeme";
+
     @BeforeClass
     public static void setupClass() throws Exception {
         kdc = new KDCServer(tmpDir.newFolder("mini-kdc_"));
@@ -58,31 +61,34 @@ public class KeytabUserIT {
 
         principal1 = new KerberosPrincipal("user1@" + kdc.getRealm());
         principal1KeytabFile = tmpDir.newFile("user1.keytab");
-        kdc.createKeytabFile(principal1KeytabFile, "user1");
+        kdc.createKeytabPrincipal(principal1KeytabFile, "user1");
 
         principal2 = new KerberosPrincipal("user2@" + kdc.getRealm());
         principal2KeytabFile = tmpDir.newFile("user2.keytab");
-        kdc.createKeytabFile(principal2KeytabFile, "user2");
+        kdc.createKeytabPrincipal(principal2KeytabFile, "user2");
+
+        principal3 = new KerberosPrincipal("user3@" + kdc.getRealm());
+        kdc.createPasswordPrincipal("user3", principal3Password);
     }
 
     @Test
-    public void testSuccessfulLoginAndLogout() throws LoginException {
+    public void testKeytabUserSuccessfulLoginAndLogout() throws LoginException 
{
         // perform login for user1
-        final KeytabUser user1 = new StandardKeytabUser(principal1.getName(), 
principal1KeytabFile.getAbsolutePath());
+        final KerberosUser user1 = new 
KerberosKeytabUser(principal1.getName(), 
principal1KeytabFile.getAbsolutePath());
         user1.login();
 
         // perform login for user2
-        final KeytabUser user2 = new StandardKeytabUser(principal2.getName(), 
principal2KeytabFile.getAbsolutePath());
+        final KerberosUser user2 = new 
KerberosKeytabUser(principal2.getName(), 
principal2KeytabFile.getAbsolutePath());
         user2.login();
 
         // verify user1 Subject only has user1 principal
-        final Subject user1Subject = ((StandardKeytabUser) user1).getSubject();
+        final Subject user1Subject = ((KerberosKeytabUser) user1).getSubject();
         final Set<Principal> user1SubjectPrincipals = 
user1Subject.getPrincipals();
         assertEquals(1, user1SubjectPrincipals.size());
         assertEquals(principal1.getName(), 
user1SubjectPrincipals.iterator().next().getName());
 
         // verify user2 Subject only has user2 principal
-        final Subject user2Subject = ((StandardKeytabUser) user2).getSubject();
+        final Subject user2Subject = ((KerberosKeytabUser) user2).getSubject();
         final Set<Principal> user2SubjectPrincipals = 
user2Subject.getPrincipals();
         assertEquals(1, user2SubjectPrincipals.size());
         assertEquals(principal2.getName(), 
user2SubjectPrincipals.iterator().next().getName());
@@ -101,9 +107,9 @@ public class KeytabUserIT {
     }
 
     @Test
-    public void testLoginWithUnknownPrincipal() throws LoginException {
+    public void testKeytabLoginWithUnknownPrincipal() throws LoginException {
         final String unknownPrincipal = "doesnotexist@" + kdc.getRealm();
-        final KeytabUser user1 = new StandardKeytabUser(unknownPrincipal, 
principal1KeytabFile.getAbsolutePath());
+        final KerberosUser user1 = new KerberosKeytabUser(unknownPrincipal, 
principal1KeytabFile.getAbsolutePath());
         try {
             user1.login();
             fail("Login should have failed");
@@ -114,8 +120,37 @@ public class KeytabUserIT {
     }
 
     @Test
+    public void testPasswordUserSuccessfulLoginAndLogout() throws 
LoginException {
+        // perform login for user
+        final KerberosUser user = new 
KerberosPasswordUser(principal3.getName(), principal3Password);
+        user.login();
+
+        // verify user Subject only has user principal
+        final Subject userSubject = ((KerberosPasswordUser) user).getSubject();
+        final Set<Principal> userSubjectPrincipals = 
userSubject.getPrincipals();
+        assertEquals(1, userSubjectPrincipals.size());
+        assertEquals(principal3.getName(), 
userSubjectPrincipals.iterator().next().getName());
+
+        // call check/relogin and verify neither user performed a relogin
+        assertFalse(user.checkTGTAndRelogin());
+
+        // perform logout for both users
+        user.logout();
+
+        // verify subjects have no more principals
+        assertEquals(0, userSubject.getPrincipals().size());
+    }
+
+    @Test(expected = LoginException.class)
+    public void testPasswordUserLoginWithInvalidPassword() throws 
LoginException {
+        // perform login for user
+        final KerberosUser user = new KerberosPasswordUser("user3", "NOT THE 
PASSWORD");
+        user.login();
+    }
+
+    @Test
     public void testCheckTGTAndRelogin() throws LoginException, 
InterruptedException {
-        final KeytabUser user1 = new StandardKeytabUser(principal1.getName(), 
principal1KeytabFile.getAbsolutePath());
+        final KerberosUser user1 = new 
KerberosKeytabUser(principal1.getName(), 
principal1KeytabFile.getAbsolutePath());
         user1.login();
 
         // Since we set the lifetime to 15 seconds we should hit a relogin 
before 15 attempts
@@ -136,7 +171,7 @@ public class KeytabUserIT {
 
     @Test
     public void testKeytabAction() {
-        final KeytabUser user1 = new StandardKeytabUser(principal1.getName(), 
principal1KeytabFile.getAbsolutePath());
+        final KerberosUser user1 = new 
KerberosKeytabUser(principal1.getName(), 
principal1KeytabFile.getAbsolutePath());
 
         final AtomicReference<String> resultHolder = new 
AtomicReference<>(null);
         final PrivilegedAction privilegedAction = () -> {
@@ -148,8 +183,8 @@ public class KeytabUserIT {
         final ComponentLog logger = Mockito.mock(ComponentLog.class);
 
         // create the action to test and execute it
-        final KeytabAction keytabAction = new KeytabAction(user1, 
privilegedAction, context, logger);
-        keytabAction.execute();
+        final KerberosAction kerberosAction = new KerberosAction(user1, 
privilegedAction, context, logger);
+        kerberosAction.execute();
 
         // if the result holder has the string success then we know the action 
executed
         assertEquals("SUCCESS", resultHolder.get());
diff --git 
a/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/TestKeytabConfiguration.java
 
b/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/TestKeytabConfiguration.java
index f105636..663fa06 100644
--- 
a/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/TestKeytabConfiguration.java
+++ 
b/nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/krb/TestKeytabConfiguration.java
@@ -39,7 +39,7 @@ public class TestKeytabConfiguration {
         assertEquals(1, entries.length);
 
         final AppConfigurationEntry entry = entries[0];
-        assertEquals(KeytabConfiguration.SUN_KRB5_LOGIN_MODULE, 
entry.getLoginModuleName());
+        assertEquals(ConfigurationUtil.SUN_KRB5_LOGIN_MODULE, 
entry.getLoginModuleName());
         assertEquals(principal, entry.getOptions().get("principal"));
         assertEquals(keytab, entry.getOptions().get("keyTab"));
     }
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 fa44b2e..4a193b6 100755
--- 
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
@@ -28,9 +28,9 @@ import org.apache.nifi.processor.AbstractProcessor;
 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.KeytabAction;
-import org.apache.nifi.security.krb.KeytabUser;
-import org.apache.nifi.security.krb.StandardKeytabUser;
+import org.apache.nifi.security.krb.KerberosAction;
+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;
 
@@ -63,7 +63,7 @@ public abstract class SolrProcessor extends AbstractProcessor 
{
     private volatile String basicPassword;
     private volatile boolean basicAuthEnabled = false;
 
-    private volatile KeytabUser keytabUser;
+    private volatile KerberosUser kerberosUser;
 
     @OnScheduled
     public final void onScheduled(final ProcessContext context) throws 
IOException {
@@ -78,12 +78,12 @@ public abstract class SolrProcessor extends 
AbstractProcessor {
 
         final KerberosCredentialsService kerberosCredentialsService = 
context.getProperty(KERBEROS_CREDENTIALS_SERVICE).asControllerService(KerberosCredentialsService.class);
         if (kerberosCredentialsService != null) {
-            this.keytabUser = createKeytabUser(kerberosCredentialsService);
+            this.kerberosUser = createKeytabUser(kerberosCredentialsService);
         }
     }
 
-    protected KeytabUser createKeytabUser(final KerberosCredentialsService 
kerberosCredentialsService) {
-        return new 
StandardKeytabUser(kerberosCredentialsService.getPrincipal(), 
kerberosCredentialsService.getKeytab());
+    protected KerberosUser createKeytabUser(final KerberosCredentialsService 
kerberosCredentialsService) {
+        return new 
KerberosKeytabUser(kerberosCredentialsService.getPrincipal(), 
kerberosCredentialsService.getKeytab());
     }
 
     @OnStopped
@@ -96,10 +96,10 @@ public abstract class SolrProcessor extends 
AbstractProcessor {
             }
         }
 
-        if (keytabUser != null) {
+        if (kerberosUser != null) {
             try {
-                keytabUser.logout();
-                keytabUser = null;
+                kerberosUser.logout();
+                kerberosUser = null;
             } catch (LoginException e) {
                 getLogger().debug("Error logging out keytab user", e);
             }
@@ -108,8 +108,8 @@ public abstract class SolrProcessor extends 
AbstractProcessor {
 
     @Override
     public final void onTrigger(final ProcessContext context, final 
ProcessSession session) throws ProcessException {
-        final KeytabUser keytabUser = getKerberosKeytabUser();
-        if (keytabUser == null) {
+        final KerberosUser kerberosUser = getKerberosKeytabUser();
+        if (kerberosUser == null) {
             doOnTrigger(context, session);
         } else {
             // wrap doOnTrigger in a privileged action
@@ -119,8 +119,8 @@ public abstract class SolrProcessor extends 
AbstractProcessor {
             };
 
             // execute the privileged action as the given keytab user
-            final KeytabAction keytabAction = new KeytabAction(keytabUser, 
action, context, getLogger());
-            keytabAction.execute();
+            final KerberosAction kerberosAction = new 
KerberosAction(kerberosUser, action, context, getLogger());
+            kerberosAction.execute();
         }
     }
 
@@ -168,8 +168,8 @@ public abstract class SolrProcessor extends 
AbstractProcessor {
         return basicAuthEnabled;
     }
 
-    protected final KeytabUser getKerberosKeytabUser() {
-        return keytabUser;
+    protected final KerberosUser getKerberosKeytabUser() {
+        return kerberosUser;
     }
 
     @Override
diff --git 
a/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/test/java/org/apache/nifi/processors/solr/TestPutSolrContentStream.java
 
b/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/test/java/org/apache/nifi/processors/solr/TestPutSolrContentStream.java
index 4eeb12a..e3c3b79 100755
--- 
a/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/test/java/org/apache/nifi/processors/solr/TestPutSolrContentStream.java
+++ 
b/nifi-nar-bundles/nifi-solr-bundle/nifi-solr-processors/src/test/java/org/apache/nifi/processors/solr/TestPutSolrContentStream.java
@@ -21,7 +21,8 @@ import org.apache.nifi.kerberos.KerberosCredentialsService;
 import org.apache.nifi.processor.ProcessContext;
 import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.reporting.InitializationException;
-import org.apache.nifi.security.krb.KeytabUser;
+import org.apache.nifi.security.krb.KerberosKeytabUser;
+import org.apache.nifi.security.krb.KerberosUser;
 import org.apache.nifi.ssl.SSLContextService;
 import org.apache.nifi.util.TestRunner;
 import org.apache.nifi.util.TestRunners;
@@ -451,10 +452,10 @@ public class TestPutSolrContentStream {
         runner.assertValid();
 
         proc.onScheduled(runner.getProcessContext());
-        final KeytabUser keytabUser = proc.getMockKerberosKeytabUser();
-        Assert.assertNotNull(keytabUser);
-        Assert.assertEquals(principal, keytabUser.getPrincipal());
-        Assert.assertEquals(keytab, keytabUser.getKeytabFile());
+        final KerberosUser kerberosUser = proc.getMockKerberosKeytabUser();;
+        Assert.assertNotNull(kerberosUser);
+        Assert.assertEquals(principal, kerberosUser.getPrincipal());
+        Assert.assertEquals(keytab, 
((KerberosKeytabUser)kerberosUser).getKeytabFile());
     }
 
     @Test
@@ -462,20 +463,20 @@ public class TestPutSolrContentStream {
         final String principal = "n...@foo.com";
         final String keytab = "src/test/resources/foo.keytab";
 
-        // Setup a mock KeytabUser that will still execute the privileged 
action
-        final KeytabUser keytabUser = Mockito.mock(KeytabUser.class);
-        when(keytabUser.getPrincipal()).thenReturn(principal);
-        when(keytabUser.getKeytabFile()).thenReturn(keytab);
-        
when(keytabUser.doAs(any(PrivilegedAction.class))).thenAnswer((invocation -> {
+        // Setup a mock KerberosUser that will still execute the privileged 
action
+        final KerberosKeytabUser kerberosUser = 
Mockito.mock(KerberosKeytabUser.class);
+        when(kerberosUser.getPrincipal()).thenReturn(principal);
+        when(kerberosUser.getKeytabFile()).thenReturn(keytab);
+        
when(kerberosUser.doAs(any(PrivilegedAction.class))).thenAnswer((invocation -> {
                     final PrivilegedAction action = (PrivilegedAction) 
invocation.getArguments()[0];
                     action.run();
                     return null;
                 })
         );
 
-        // Configure the processor with the mock KeytabUser and with a 
credentials service
+        // Configure the processor with the mock KerberosUser and with a 
credentials service
         final SolrClient solrClient = 
createEmbeddedSolrClient(DEFAULT_SOLR_CORE);
-        final TestableProcessor proc = new TestableProcessor(solrClient, 
keytabUser);
+        final TestableProcessor proc = new TestableProcessor(solrClient, 
kerberosUser);
         final TestRunner runner = createDefaultTestRunner(proc);
 
         final KerberosCredentialsService kerberosCredentialsService = new 
MockKerberosCredentialsService(principal, keytab);
@@ -499,9 +500,9 @@ public class TestPutSolrContentStream {
         }
 
         // Verify that during the update the user was logged in, TGT was 
checked, and the action was executed
-        verify(keytabUser, times(1)).login();
-        verify(keytabUser, times(1)).checkTGTAndRelogin();
-        verify(keytabUser, times(1)).doAs(any(PrivilegedAction.class));
+        verify(kerberosUser, times(1)).login();
+        verify(kerberosUser, times(1)).checkTGTAndRelogin();
+        verify(kerberosUser, times(1)).doAs(any(PrivilegedAction.class));
     }
 
 
@@ -647,15 +648,15 @@ public class TestPutSolrContentStream {
     // Override createSolrClient and return the passed in SolrClient
     private class TestableProcessor extends PutSolrContentStream {
         private SolrClient solrClient;
-        private KeytabUser keytabUser;
+        private KerberosUser kerberosUser;
 
         public TestableProcessor(SolrClient solrClient) {
             this.solrClient = solrClient;
         }
 
-        public TestableProcessor(SolrClient solrClient, KeytabUser keytabUser) 
{
+        public TestableProcessor(SolrClient solrClient, KerberosUser 
kerberosUser) {
             this.solrClient = solrClient;
-            this.keytabUser = keytabUser;
+            this.kerberosUser = kerberosUser;
         }
 
         @Override
@@ -664,15 +665,15 @@ public class TestPutSolrContentStream {
         }
 
         @Override
-        protected KeytabUser createKeytabUser(KerberosCredentialsService 
kerberosCredentialsService) {
-            if (keytabUser != null) {
-                return keytabUser;
+        protected KerberosUser createKeytabUser(KerberosCredentialsService 
kerberosCredentialsService) {
+            if (kerberosUser != null) {
+                return kerberosUser;
             } else {
                 return super.createKeytabUser(kerberosCredentialsService);
             }
         }
 
-        public KeytabUser getMockKerberosKeytabUser() {
+        public KerberosUser getMockKerberosKeytabUser() {
             return super.getKerberosKeytabUser();
         }
     }

Reply via email to