adjust to use password-service 69/72169/5
authorRyan Goulding <ryandgoulding@gmail.com>
Thu, 17 May 2018 20:13:26 +0000 (16:13 -0400)
committerTom Pantelis <tompantelis@gmail.com>
Wed, 30 May 2018 18:29:16 +0000 (14:29 -0400)
Use the simplified password-service instead of SHA256Calculator.
After all, SHA256Calculator is deprecated since it combines API
and IMPL even in the name!

This is also more configurable and secure.

Change-Id: I471e0fe1d11d6b65ab574c5286ce1a874a2231fb
Signed-off-by: Ryan Goulding <ryandgoulding@gmail.com>
38 files changed:
aaa-cli-jar/pom.xml
aaa-cli-jar/src/main/java/org/opendaylight/aaa/cli/jar/StandaloneCommandLineInterface.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/AaaCliAbstractCommand.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddDomain.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddGrant.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddRole.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddUser.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ChangeUserPassword.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLDomains.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLRoles.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLUsers.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveDomain.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveGrant.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveRole.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveUser.java
aaa-cli/src/main/java/org/opendaylight/aaa/cli/utils/DataStoreUtils.java
aaa-cli/src/main/resources/org/opendaylight/blueprint/commands.xml
aaa-cli/src/test/java/org/opendaylight/aaa/cli/test/AaaCliAbstractCommandTest.java
aaa-password-service/impl/pom.xml
aaa-password-service/impl/src/main/java/org/opendaylight/aaa/impl/password/service/DefaultPasswordHashService.java
aaa-password-service/impl/src/main/resources/org/opendaylight/blueprint/password-service-blueprint.xml
aaa-shiro/impl/pom.xml
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/AAAShiroProvider.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/H2Store.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/UserStore.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/idm/IdmLightProxy.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/realm/MdsalRealm.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/AAAIniWebEnvironment.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ShiroWebEnvironmentLoaderListener.java
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ThreadLocals.java
aaa-shiro/impl/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml
aaa-shiro/impl/src/test/java/org/opendaylight/aaa/datastore/h2/H2StoreTest.java
aaa-shiro/impl/src/test/java/org/opendaylight/aaa/datastore/h2/UserStoreTest.java
aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/persistence/PasswordHashTest.java
aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/rest/test/HandlerTest.java
features/odl-aaa-shiro/pom.xml
features/odl-aaa-shiro/src/main/feature/feature.xml

index 682fb87fda65d4d5d03ff180da9a299e6dade357..4565a7f04546016f58ab945ce1a0963680ed29ec 100644 (file)
@@ -85,6 +85,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>testutils</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>aaa-password-service-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.aaa</groupId>
+      <artifactId>aaa-password-service-impl</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
@@ -152,6 +160,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
                     <include>org/h2/constraint/**</include>
                   </includes>
                 </filter>
+                <filter>
+                  <artifact>org.opendaylight.aaa:aaa-password-service-api</artifact>
+                  <includes>
+                    <include>org/opendaylight/**</include>
+                  </includes>
+                </filter>
+                <filter>
+                  <artifact>org.opendaylight.aaa:aaa-password-service-impl</artifact>
+                  <includes>
+                    <include>org/opendaylight/**</include>
+                  </includes>
+                </filter>
               </filters>
               <transformers>
                 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
index b33e6356fa44443904461cec3fe1555f93f459dc..3de3f55bf07da6c8d48121efb6aa62d4cbff95d2 100644 (file)
@@ -15,13 +15,14 @@ import java.util.Optional;
 import java.util.stream.Collectors;
 import org.opendaylight.aaa.api.IDMStoreException;
 import org.opendaylight.aaa.api.IIDMStore;
-import org.opendaylight.aaa.api.SHA256Calculator;
 import org.opendaylight.aaa.api.StoreBuilder;
 import org.opendaylight.aaa.api.model.User;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.datastore.h2.H2Store;
 import org.opendaylight.aaa.datastore.h2.IdmLightConfig;
 import org.opendaylight.aaa.datastore.h2.IdmLightConfigBuilder;
 import org.opendaylight.aaa.datastore.h2.IdmLightSimpleConnectionProvider;
+import org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService;
 
 /**
  * AAA CLI interface.
@@ -34,13 +35,16 @@ public class StandaloneCommandLineInterface {
     private final IIDMStore identityStore;
     private final StoreBuilder storeBuilder;
     private static final String DOMAIN = IIDMStore.DEFAULT_DOMAIN;
+    private final PasswordHashService passwordService;
 
     public StandaloneCommandLineInterface(File directoryWithDatabaseFile) throws IOException, IDMStoreException {
         IdmLightConfigBuilder configBuider = new IdmLightConfigBuilder();
         configBuider.dbDirectory(directoryWithDatabaseFile.getCanonicalPath()).dbUser("foo").dbPwd("bar");
         IdmLightConfig config = configBuider.build();
 
-        H2Store h2Store = new H2Store(new IdmLightSimpleConnectionProvider(config));
+        passwordService = new DefaultPasswordHashService();
+
+        H2Store h2Store = new H2Store(new IdmLightSimpleConnectionProvider(config), passwordService);
         this.identityStore = h2Store;
 
         this.storeBuilder = new StoreBuilder(h2Store);
@@ -74,8 +78,7 @@ public class StandaloneCommandLineInterface {
             return false;
         } else {
             User user = optUser.get();
-            String realPwd = SHA256Calculator.getSHA256(password, user.getSalt());
-            return user.getPassword().equals(realPwd);
+            return passwordService.passwordsMatch(password, user.getPassword(), user.getSalt());
         }
     }
 
index 92fb9114234014e85ff88e4d1f93577784444e83..d9831b55624df47d695c90cc383bde1dafaa8ea4 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.aaa.cli;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.util.Objects;
 import org.apache.karaf.shell.console.OsgiCommandSupport;
 import org.opendaylight.aaa.api.IIDMStore;
 import org.opendaylight.aaa.api.model.User;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
 
@@ -25,6 +27,11 @@ public abstract class AaaCliAbstractCommand extends OsgiCommandSupport {
 
     private static volatile String authUser = null;
     protected IIDMStore identityStore;
+    private final PasswordHashService passwordService;
+
+    public AaaCliAbstractCommand(final PasswordHashService passwordService) {
+        Objects.requireNonNull(this.passwordService = passwordService);
+    }
 
     public void setIdentityStore(IIDMStore identityStore) {
         this.identityStore = identityStore;
@@ -36,7 +43,7 @@ public abstract class AaaCliAbstractCommand extends OsgiCommandSupport {
         if (currentUser == null) {
             final String userName = CliUtils.readPassword(super.session, "Enter Username:");
             final String passwd = CliUtils.readPassword(super.session, "Enter Password:");
-            final User usr = DataStoreUtils.isAdminUser(identityStore, userName, passwd);
+            final User usr = DataStoreUtils.isAdminUser(identityStore, passwordService, userName, passwd);
             if (usr != null) {
                 authUser = userName;
                 SessionsManager.getInstance().addUserSession(userName, usr);
index a42637cb03cedb666839a57abba5332cee0ec995..2fe7e554cf3248c5d1e26f9de133362e8a98b46d 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.model.Domain;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.slf4j.Logger;
@@ -34,8 +35,8 @@ public class AddDomain extends AaaCliAbstractCommand {
             "--domainDescription" }, description = "The domain Description", required = true, multiValued = false)
     private String domainDesc = "";
 
-    public AddDomain() {
-        super();
+    public AddDomain(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index 95ea9ff69c1438a7052d95f40e6bd7a3e1f84caa..e9074d82a6ba40eed8f00239ad177f41eb92bb72 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.model.Grant;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -35,8 +36,8 @@ public class AddGrant extends AaaCliAbstractCommand {
             "--roleName" }, description = "The role name", required = false, multiValued = false)
     private String roleName = "";
 
-    public AddGrant() {
-        super();
+    public AddGrant(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index 9506b587868d96f60bf34293bf063b2eefe06947..99ccf1a198a9d978a711c19903db7ccd3d7d14ba 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.model.Role;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -35,8 +36,8 @@ public class AddRole extends AaaCliAbstractCommand {
             "--roleDescription" }, description = "The role Description", required = true, multiValued = false)
     private String roleDesc = "";
 
-    public AddRole() {
-        super();
+    public AddRole(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index ac979f04396e74894be898e3cc77824ee033e5ee..59efb3cd53b1bfa7c29787a72f9204da9c2d4bde 100644 (file)
@@ -12,6 +12,7 @@ import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.model.Grant;
 import org.opendaylight.aaa.api.model.User;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -59,8 +60,8 @@ public class AddUser extends AaaCliAbstractCommand {
             multiValued = false)
     private String userEmail = "";
 
-    public AddUser() {
-        super();
+    public AddUser(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index b4b35d7f0a280902969bae24a02fd9db30ef96f0..3959babdc3cc3749f71f4bbea69c04dfb3249355 100644 (file)
@@ -13,9 +13,9 @@ import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.console.OsgiCommandSupport;
 import org.opendaylight.aaa.api.ClaimCache;
 import org.opendaylight.aaa.api.IIDMStore;
-import org.opendaylight.aaa.api.SHA256Calculator;
 import org.opendaylight.aaa.api.model.User;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 
 @Command(name = "change-user-pwd", scope = "aaa", description = "Change the user password.")
@@ -35,9 +35,14 @@ public class ChangeUserPassword extends OsgiCommandSupport {
             "--userName" }, description = "The user name", required = true, multiValued = false)
     private String userName;
 
-    public ChangeUserPassword(IIDMStore identityStore, ClaimCache claimCache) {
+    private final PasswordHashService passwordService;
+
+    public ChangeUserPassword(final IIDMStore identityStore, final ClaimCache claimCache,
+                              final PasswordHashService passwordService) {
+
         this.identityStore = identityStore;
         this.claimCache = claimCache;
+        this.passwordService = passwordService;
     }
 
     @Override
@@ -49,8 +54,8 @@ public class ChangeUserPassword extends OsgiCommandSupport {
         final String newPwd = CliUtils.readPassword(this.session, "Enter new password:");
         final Users users = identityStore.getUsers();
         for (User usr : users.getUsers()) {
-            final String realPwd = SHA256Calculator.getSHA256(currentPwd, usr.getSalt());
-            if (usr.getName().equals(userName) && usr.getPassword().equals(realPwd)) {
+            if (usr.getName().equals(userName)
+                    && passwordService.passwordsMatch(currentPwd, usr.getPassword(), usr.getSalt())) {
                 claimCache.clear();
                 usr.setPassword(newPwd);
                 identityStore.updateUser(usr);
index 183700bd11c148461507b0df009072e03a8a2484..b6403041956691073847d166f707cd80f30cd178 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.aaa.cli.dmstore;
 
 import org.apache.karaf.shell.commands.Command;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 
@@ -22,8 +23,8 @@ import org.opendaylight.aaa.cli.utils.CliUtils;
  */
 public class ListODLDomains extends AaaCliAbstractCommand {
 
-    public ListODLDomains() {
-        super();
+    public ListODLDomains(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index 4f63cc26602eb56ab65a2429c92e3e26265a7a6a..b21f92b6b19f2f78d85c9e038e37d83be2f71fd7 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.aaa.cli.dmstore;
 
 import org.apache.karaf.shell.commands.Command;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 
@@ -22,8 +23,8 @@ import org.opendaylight.aaa.cli.utils.CliUtils;
  */
 public class ListODLRoles extends AaaCliAbstractCommand {
 
-    public ListODLRoles() {
-        super();
+    public ListODLRoles(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index ba43df6718cf21f746e7b2e4695a3cc96a8f8d41..144ff3fba5eee7f0932b586f8caa1ac0744488d6 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.aaa.cli.dmstore;
 
 import org.apache.karaf.shell.commands.Command;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 
@@ -22,8 +23,8 @@ import org.opendaylight.aaa.cli.utils.CliUtils;
  */
 public class ListODLUsers extends AaaCliAbstractCommand {
 
-    public ListODLUsers() {
-        super();
+    public ListODLUsers(final PasswordHashService passwordService) {
+        super(passwordService);
     }
 
     @Override
index 1881021bd633f0b9be34ed630936f05f55f1dfdf..ba5611fefda990536757ac4713756f3765a2864c 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.ClaimCache;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -29,7 +30,8 @@ public class RemoveDomain extends AaaCliAbstractCommand {
             "--domainName" }, description = "The domain name", required = true, multiValued = false)
     private String domainName;
 
-    public RemoveDomain(ClaimCache claimCache) {
+    public RemoveDomain(final ClaimCache claimCache, final PasswordHashService passwordService) {
+        super(passwordService);
         this.claimCache = claimCache;
     }
 
index dd603c29fba7e68cbeb742f7695ac1ea5bb9a4ef..fd79193e483d36f08f9906db8c122d902b761b51 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.ClaimCache;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -37,7 +38,8 @@ public class RemoveGrant extends AaaCliAbstractCommand {
             "--roleName" }, description = "The role name", required = false, multiValued = false)
     private String roleName;
 
-    public RemoveGrant(ClaimCache claimCache) {
+    public RemoveGrant(final ClaimCache claimCache, final PasswordHashService passwordService) {
+        super(passwordService);
         this.claimCache = claimCache;
     }
 
index 077d3fe2f952fe2cbf87944312decf5da506b13b..5da16d3f3904a459684642a8fd5fad103d1b6c51 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.ClaimCache;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -29,7 +30,8 @@ public class RemoveRole extends AaaCliAbstractCommand {
             "--roleName" }, description = "The role name", required = true, multiValued = false)
     private String roleName;
 
-    public RemoveRole(ClaimCache claimCache) {
+    public RemoveRole(final ClaimCache claimCache, final PasswordHashService passwordService) {
+        super(passwordService);
         this.claimCache = claimCache;
     }
 
index c65e7d38b62a102041b3b999c9d4e97dfe657ef6..16b533ffecf3f3168cf88fdbe3623f0a71eb0477 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.aaa.cli.dmstore;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.opendaylight.aaa.api.ClaimCache;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cli.AaaCliAbstractCommand;
 import org.opendaylight.aaa.cli.utils.CliUtils;
 import org.opendaylight.aaa.cli.utils.DataStoreUtils;
@@ -29,7 +30,8 @@ public class RemoveUser extends AaaCliAbstractCommand {
             "--userName" }, description = "The user name", required = true, multiValued = false)
     private String userName;
 
-    public RemoveUser(ClaimCache claimCache) {
+    public RemoveUser(final ClaimCache claimCache, final PasswordHashService passwordService) {
+        super(passwordService);
         this.claimCache = claimCache;
     }
 
index b7a0e758a59d242e78f90325f9ca0e5ad6e39822..98207641a88f04ab547643588afda7dbc60d1923 100644 (file)
@@ -11,13 +11,13 @@ package org.opendaylight.aaa.cli.utils;
 import java.util.List;
 import org.opendaylight.aaa.api.IDMStoreException;
 import org.opendaylight.aaa.api.IIDMStore;
-import org.opendaylight.aaa.api.SHA256Calculator;
 import org.opendaylight.aaa.api.model.Domain;
 import org.opendaylight.aaa.api.model.Domains;
 import org.opendaylight.aaa.api.model.Grant;
 import org.opendaylight.aaa.api.model.Role;
 import org.opendaylight.aaa.api.model.User;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,7 +62,8 @@ public final class DataStoreUtils {
         return null;
     }
 
-    public static String getGrantId(IIDMStore identityStore, String domainName, String roleName, String userName)
+    public static String getGrantId(IIDMStore identityStore, String domainName, String roleName,
+                                    String userName)
             throws IDMStoreException {
         final String domainId = getDomainId(identityStore, domainName);
         if (domainId == null) {
@@ -88,11 +89,13 @@ public final class DataStoreUtils {
         return null;
     }
 
-    public static User isAdminUser(IIDMStore identityStore, String userName, String password) throws IDMStoreException {
+    public static User isAdminUser(IIDMStore identityStore, PasswordHashService passwordService,
+                                   String userName, String password) throws IDMStoreException {
+
         final Users users = identityStore.getUsers();
         for (User usr : users.getUsers()) {
-            final String realPwd = SHA256Calculator.getSHA256(password, usr.getSalt());
-            if (usr.getName().equals(userName) && usr.getPassword().equals(realPwd)) {
+            if (usr.getName().equals(userName)
+                    && passwordService.passwordsMatch(password, usr.getPassword(), usr.getSalt())) {
                 List<Grant> grants = identityStore.getGrants(usr.getUserid()).getGrants();
                 if (grants != null && !grants.isEmpty()) {
                     final String adminRoleId = getRoleId(identityStore, ADMIN_ROLE);
index 069e1cb2d37bd1aa0a1cb89b8fd2abda764f226b..b7a50aa2955b63a59a70c3ce83fb8876415f442c 100644 (file)
 
     <reference id="iIDMStore" interface="org.opendaylight.aaa.api.IIDMStore" />
     <reference id="claimCache" interface="org.opendaylight.aaa.api.ClaimCache" />
+    <reference id="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordHashService" />
 
     <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.ListODLUsers">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.ListODLDomains">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.ListODLRoles">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.ChangeUserPassword">
                 <argument ref="iIDMStore" />
                 <argument ref="claimCache" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.GetODLSelfSignCert">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.GenerateCertReq">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.GetTrustStoreCert">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.GetCipherSuites">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.GetTlsProtocols">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.ExportDefaultKeystores">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.cert.ImportDefaultKeystores">
                 <argument ref="KeyStoreConsoleProvider" />
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.AddRole">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.AddDomain">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.AddUser">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.AddGrant">
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.RemoveGrant">
                 <argument ref="claimCache" />
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.RemoveUser">
                 <argument ref="claimCache" />
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.RemoveRole">
                 <argument ref="claimCache" />
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
         <command>
             <action class="org.opendaylight.aaa.cli.dmstore.RemoveDomain">
                 <argument ref="claimCache" />
                 <property name="identityStore" ref="iIDMStore"/>
+                <argument ref="passwordService" />
             </action>
         </command>
     </command-bundle>
index fdc428c42d41215f2bb185a729b077b42c3f681f..5fc1dd865238554edf1b4ff5d97fdd33b4368a09 100644 (file)
@@ -34,7 +34,7 @@ public class AaaCliAbstractCommandTest {
     class TestAaaCliAbstractCommand extends AaaCliAbstractCommand {
 
         TestAaaCliAbstractCommand() {
-            super();
+            super(null);
         }
 
         @Override
index 0cfdcf93f5f241daadb449f786dc9adea4f4d972..e24015afc1690731936c458dd13c9071edaee2c9 100644 (file)
@@ -37,6 +37,25 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
 
   <build>
     <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <!--
+            DefaultPasswordHashService is intentionally exported here for internal use by aaa-cli-jar.  In general,
+            it is bad SOA practice to export implementation bundles.  This was done in order to fulfill a specific
+            non-OSGi requirement that uses this implementation directly.  Outside consumers should consider
+            getting the Service through querying the OSGi registry for
+            org.opendaylight.aaa.api.password.service.PasswordHashService implementations instead.
+            -->
+            <Export-Package>
+              org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService
+            </Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
@@ -49,7 +68,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             </goals>
             <configuration>
               <artifacts>
-                <!-- attach aaa-app-config.xml as an artifact -->
                 <artifact>
                   <file>${project.build.directory}/classes/initial/aaa-password-service-config.xml</file>
                   <type>xml</type>
index 151e15055406dd8f1274ddfbc5ccfbd6d0a1145c..90faa3230033f691a7693ed0b57b03bbebf6b1e9 100644 (file)
@@ -26,11 +26,19 @@ public class DefaultPasswordHashService implements PasswordHashService {
     private static final Logger LOG = LoggerFactory.getLogger(DefaultPasswordHashService.class);
 
     public static final String DEFAULT_HASH_ALGORITHM = "SHA-512";
-    public static final int DEFAULT_NUM_ITERATIONS = 10000;
+    public static final int DEFAULT_NUM_ITERATIONS = 20000;
 
     private final DefaultHashService hashService = new DefaultHashService();
 
+    public DefaultPasswordHashService() {
+        hashService.setRandomNumberGenerator(new SecureRandomNumberGenerator());
+        hashService.setGeneratePublicSalt(true);
+        setNumIterations(Optional.of(DEFAULT_NUM_ITERATIONS));
+        setHashAlgorithm(Optional.of(DEFAULT_HASH_ALGORITHM));
+    }
+
     public DefaultPasswordHashService(final PasswordServiceConfig passwordServiceConfig) {
+        this();
         final Optional<Integer> numIterationsOptional = Optional.ofNullable(passwordServiceConfig.getIterations());
         setNumIterations(numIterationsOptional);
 
@@ -39,9 +47,6 @@ public class DefaultPasswordHashService implements PasswordHashService {
 
         final Optional<String> privateSaltOptional = Optional.ofNullable(passwordServiceConfig.getPrivateSalt());
         setPrivateSalt(privateSaltOptional);
-
-        hashService.setRandomNumberGenerator(new SecureRandomNumberGenerator());
-        hashService.setGeneratePublicSalt(true);
     }
 
     private void setNumIterations(final Optional<Integer> numIterationsOptional) {
index 752a1b0b6328cb73a32fb92529695f343c6ef54d..019493c037c2ffd89f0a671f5a456a6a86e56af0 100644 (file)
@@ -18,7 +18,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <bean id="passwordService" class="org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService">
         <argument ref="passwordServiceConfig" />
     </bean>
-    <service ref="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordService"
+    <service ref="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordHashService"
         odl:type="default"/>
 
 </blueprint>
index aa935377c8134988d95ad4e74720cf431ce89bfb..b076fb9de6fed8c0f1349ec5c46f7547f9f6bdf0 100644 (file)
@@ -90,6 +90,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <groupId>org.opendaylight.aaa</groupId>
             <artifactId>aaa-filterchain</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-password-service-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
@@ -176,6 +180,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <groupId>com.google.truth</groupId>
             <artifactId>truth</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-password-service-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 42a7cda6ea89d18fe2fb593d5f00ca77607b1c29..3e9bf7ffa1754def226226d7124dd71648329f5e 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.aaa.api.IdMServiceImpl;
 import org.opendaylight.aaa.api.PasswordCredentials;
 import org.opendaylight.aaa.api.StoreBuilder;
 import org.opendaylight.aaa.api.TokenStore;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cert.api.ICertificateManager;
 import org.opendaylight.aaa.datastore.h2.H2TokenStore;
 import org.opendaylight.aaa.shiro.oauth2.OAuth2TokenServlet;
@@ -50,6 +51,7 @@ public final class AAAShiroProvider {
     private final String oauth2EndpointPath;
     private final TokenAuthenticators tokenAuthenticators;
     private final AuthenticationService authenticationService;
+    private final PasswordHashService passwordHashService;
 
     /**
      * Constructor.
@@ -63,7 +65,8 @@ public final class AAAShiroProvider {
                             final String oauth2EndpointPath,
                             final DatastoreConfig datastoreConfig,
                             final IIDMStore iidmStore,
-                            final AuthenticationService authenticationService) {
+                            final AuthenticationService authenticationService,
+                            final PasswordHashService passwordHashService) {
         this.dataBroker = dataBroker;
         this.certificateManager = certificateManager;
         this.shiroConfiguration = shiroConfiguration;
@@ -71,6 +74,7 @@ public final class AAAShiroProvider {
         this.moonEndpointPath = moonEndpointPath;
         this.oauth2EndpointPath = oauth2EndpointPath;
         this.authenticationService = authenticationService;
+        this.passwordHashService = passwordHashService;
 
         if (datastoreConfig == null || !datastoreConfig.getStore().equals(DatastoreConfig.Store.H2DataStore)) {
             LOG.info("AAA Datastore has not been initialized");
@@ -177,4 +181,8 @@ public final class AAAShiroProvider {
     public AuthenticationService getAuthenticationService() {
         return authenticationService;
     }
+
+    public PasswordHashService getPasswordHashService() {
+        return passwordHashService;
+    }
 }
index 78334bd763dfd6fcb51d7653c2d0a817dd9c1211..a6abdc98dfe0beddf849ddc7e65df599d9b61033 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.aaa.api.model.Role;
 import org.opendaylight.aaa.api.model.Roles;
 import org.opendaylight.aaa.api.model.User;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,14 +32,14 @@ public class H2Store implements IIDMStore {
     private final RoleStore roleStore;
     private final GrantStore grantStore;
 
-    public H2Store(String dbUsername, String dbPassword) {
+    public H2Store(final String dbUsername, final String dbPassword, final PasswordHashService passwordService) {
         this(new IdmLightSimpleConnectionProvider(
-                new IdmLightConfigBuilder().dbUser(dbUsername).dbPwd(dbPassword).build()));
+                new IdmLightConfigBuilder().dbUser(dbUsername).dbPwd(dbPassword).build()), passwordService);
     }
 
-    public H2Store(ConnectionProvider connectionFactory) {
+    public H2Store(ConnectionProvider connectionFactory, final PasswordHashService passwordService) {
         this.domainStore = new DomainStore(connectionFactory);
-        this.userStore = new UserStore(connectionFactory);
+        this.userStore = new UserStore(connectionFactory, passwordService);
         this.roleStore = new RoleStore(connectionFactory);
         this.grantStore = new GrantStore(connectionFactory);
     }
index 8280b68056d66b57f13394cf3c13cf8f884f0f1b..85eecaab1ebbdf6041de24211ec3555eb6537eb3 100644 (file)
@@ -15,11 +15,13 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Objects;
 import org.apache.commons.text.StringEscapeUtils;
 import org.opendaylight.aaa.api.IDMStoreUtil;
-import org.opendaylight.aaa.api.SHA256Calculator;
 import org.opendaylight.aaa.api.model.User;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.api.password.service.PasswordHash;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,8 +44,11 @@ public class UserStore extends AbstractStore<User> {
     public static final String SQL_SALT = "salt";
     private static final String TABLE_NAME = "USERS";
 
-    public UserStore(ConnectionProvider dbConnectionFactory) {
+    private final PasswordHashService passwordService;
+
+    public UserStore(ConnectionProvider dbConnectionFactory, final PasswordHashService passwordService) {
         super(dbConnectionFactory, TABLE_NAME);
+        this.passwordService = Objects.requireNonNull(passwordService);
     }
 
     @Override
@@ -51,7 +56,7 @@ public class UserStore extends AbstractStore<User> {
         return "CREATE TABLE users " + "(userid    VARCHAR(128) PRIMARY KEY,"
                 + "name       VARCHAR(128)      NOT NULL, " + "domainid   VARCHAR(128)      NOT NULL, "
                 + "email      VARCHAR(128)      NOT NULL, " + "password   VARCHAR(128)      NOT NULL, "
-                + "description VARCHAR(128)     NOT NULL, " + "salt        VARCHAR(15)      NOT NULL, "
+                + "description VARCHAR(128)     NOT NULL, " + "salt        VARCHAR(128)      NOT NULL, "
                 + "enabled     INTEGER          NOT NULL)";
     }
 
@@ -111,7 +116,8 @@ public class UserStore extends AbstractStore<User> {
         Preconditions.checkNotNull(user.getName());
         Preconditions.checkNotNull(user.getDomainid());
 
-        user.setSalt(SHA256Calculator.generateSALT());
+        final PasswordHash passwordHash = passwordService.getPasswordHash(user.getPassword());
+        user.setSalt(passwordHash.getSalt());
         String query =
                 "insert into users"
                 + " (userid,domainid,name,email,password,description,enabled,salt) values(?,?,?,?,?,?,?,?)";
@@ -121,7 +127,7 @@ public class UserStore extends AbstractStore<User> {
             statement.setString(2, user.getDomainid());
             statement.setString(3, user.getName());
             statement.setString(4, user.getEmail());
-            statement.setString(5, SHA256Calculator.getSHA256(user.getPassword(), user.getSalt()));
+            statement.setString(5, passwordHash.getHashedPassword());
             statement.setString(6, user.getDescription());
             statement.setInt(7, user.isEnabled() ? 1 : 0);
             statement.setString(8, user.getSalt());
@@ -161,7 +167,8 @@ public class UserStore extends AbstractStore<User> {
             if (salt == null) {
                 salt = savedUser.getSalt();
             }
-            savedUser.setPassword(SHA256Calculator.getSHA256(user.getPassword(), salt));
+            final PasswordHash passwordHash = passwordService.getPasswordHash(user.getPassword(), salt);
+            savedUser.setPassword(passwordHash.getHashedPassword());
         }
 
         String query = "UPDATE users SET email = ?, password = ?, description = ?, enabled = ? WHERE userid = ?";
index 116f7a99c175b39347b3b16b229fd9cd48b0b1cb..65db8e67fc84eec7e56e91906d2d6feeb110821a 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.annotation.Nonnull;
 import org.opendaylight.aaa.api.AuthenticationException;
@@ -22,13 +23,13 @@ import org.opendaylight.aaa.api.IIDMStore;
 import org.opendaylight.aaa.api.IdMService;
 import org.opendaylight.aaa.api.IdMServiceImpl;
 import org.opendaylight.aaa.api.PasswordCredentials;
-import org.opendaylight.aaa.api.SHA256Calculator;
 import org.opendaylight.aaa.api.model.Domain;
 import org.opendaylight.aaa.api.model.Grant;
 import org.opendaylight.aaa.api.model.Grants;
 import org.opendaylight.aaa.api.model.Role;
 import org.opendaylight.aaa.api.model.User;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.shiro.tokenauthrealm.auth.ClaimBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,9 +48,11 @@ public class IdmLightProxy implements CredentialAuth<PasswordCredentials>, IdMSe
     private final Map<String, Map<PasswordCredentials, Claim>> claimCache = new ConcurrentHashMap<>();
 
     private final IIDMStore idmStore;
+    private final PasswordHashService passwordService;
 
-    public IdmLightProxy(IIDMStore idmStore) {
+    public IdmLightProxy(IIDMStore idmStore, PasswordHashService passwordService) {
         this.idmStore = idmStore;
+        this.passwordService = Objects.requireNonNull(passwordService);
     }
 
     @Override
@@ -100,8 +103,7 @@ public class IdmLightProxy implements CredentialAuth<PasswordCredentials>, IdMSe
                         + " does not exist in domain " + credsDomain);
             }
             user = userList.get(0);
-            if (!SHA256Calculator.getSHA256(creds.password(), user.getSalt()).equals(
-                    user.getPassword())) {
+            if (!passwordService.passwordsMatch(creds.password(), user.getPassword(), user.getSalt())) {
                 throw new AuthenticationException("UserName / Password not found");
             }
             if (!user.isEnabled()) {
index 3d4db766e5a3bf6a335a26a75245c73de4d53f30..8a7707342ce8feb354278bfbda9905489d9b3631 100644 (file)
@@ -23,7 +23,7 @@ import org.apache.shiro.authz.AuthorizationInfo;
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
 import org.apache.shiro.realm.AuthorizingRealm;
 import org.apache.shiro.subject.PrincipalCollection;
-import org.opendaylight.aaa.api.SHA256Calculator;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal;
 import org.opendaylight.aaa.shiro.principal.ODLPrincipalImpl;
 import org.opendaylight.aaa.shiro.realm.util.TokenUtils;
@@ -56,9 +56,11 @@ public class MdsalRealm extends AuthorizingRealm {
             InstanceIdentifier.builder(Authentication.class).build();
 
     private final DataBroker dataBroker;
+    private final PasswordHashService passwordHashService;
 
     public MdsalRealm() {
         this.dataBroker = Objects.requireNonNull(ThreadLocals.DATABROKER_TL.get());
+        this.passwordHashService = Objects.requireNonNull(ThreadLocals.PASSWORD_HASH_SERVICE_TL.get());
         LOG.info("MdsalRealm created");
     }
 
@@ -134,8 +136,7 @@ public class MdsalRealm extends AuthorizingRealm {
                 }
                 if (userEnabled && u.getUserid().equals(inputUserId)) {
                     final String inputPassword = TokenUtils.extractPassword(authenticationToken);
-                    final String hashedInputPassword = SHA256Calculator.getSHA256(inputPassword, u.getSalt());
-                    if (hashedInputPassword.equals(u.getPassword())) {
+                    if (passwordHashService.passwordsMatch(inputPassword, u.getPassword(), u.getSalt())) {
                         final ODLPrincipal odlPrincipal = ODLPrincipalImpl
                                 .createODLPrincipal(inputUsername, domainId, inputUserId);
                         return new SimpleAuthenticationInfo(odlPrincipal, inputPassword, getName());
index 55e78e2b6ef7bb0a0808760f67d1a0cf3786f094..5ac0bd44159d0218e68289e9ce6e671be185ec8f 100644 (file)
@@ -17,6 +17,7 @@ import org.apache.shiro.util.Factory;
 import org.apache.shiro.web.env.IniWebEnvironment;
 import org.opendaylight.aaa.api.AuthenticationService;
 import org.opendaylight.aaa.api.TokenStore;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cert.api.ICertificateManager;
 import org.opendaylight.aaa.shiro.tokenauthrealm.auth.TokenAuthenticators;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -48,16 +49,19 @@ class AAAIniWebEnvironment extends IniWebEnvironment {
     private final AuthenticationService authenticationService;
     private final TokenAuthenticators tokenAuthenticators;
     private final TokenStore tokenStore;
+    private final PasswordHashService passwordHashService;
 
     AAAIniWebEnvironment(ShiroConfiguration shiroConfiguration, DataBroker dataBroker,
-            ICertificateManager certificateManager, AuthenticationService authenticationService,
-            TokenAuthenticators tokenAuthenticators, TokenStore tokenStore) {
+                         ICertificateManager certificateManager, AuthenticationService authenticationService,
+                         TokenAuthenticators tokenAuthenticators, TokenStore tokenStore,
+                         PasswordHashService passwordHashService) {
         this.shiroConfiguration = shiroConfiguration;
         this.dataBroker = dataBroker;
         this.certificateManager = certificateManager;
         this.authenticationService = authenticationService;
         this.tokenAuthenticators = tokenAuthenticators;
         this.tokenStore = tokenStore;
+        this.passwordHashService = passwordHashService;
         LOG.debug("AAAIniWebEnvironment created");
     }
 
@@ -91,6 +95,7 @@ class AAAIniWebEnvironment extends IniWebEnvironment {
         ThreadLocals.AUTH_SETVICE_TL.set(authenticationService);
         ThreadLocals.TOKEN_AUTHENICATORS_TL.set(tokenAuthenticators);
         ThreadLocals.TOKEN_STORE_TL.set(tokenStore);
+        ThreadLocals.PASSWORD_HASH_SERVICE_TL.set(passwordHashService);
         try {
             // Initialize the Shiro environment from clustered-app-config
             final Ini ini = createIniFromClusteredAppConfig(shiroConfiguration);
@@ -105,6 +110,7 @@ class AAAIniWebEnvironment extends IniWebEnvironment {
             ThreadLocals.AUTH_SETVICE_TL.remove();
             ThreadLocals.TOKEN_AUTHENICATORS_TL.remove();
             ThreadLocals.TOKEN_STORE_TL.remove();
+            ThreadLocals.PASSWORD_HASH_SERVICE_TL.remove();
         }
     }
 }
index b06e6fddbe9107d6922dc735277541bdcd0b0836..f88924900dbac843673f157fb7b88a52e8c80dd1 100644 (file)
@@ -45,6 +45,7 @@ public class KarafIniWebEnvironment extends IniWebEnvironment {
             ThreadLocals.AUTH_SETVICE_TL.set(provider.getAuthenticationService());
             ThreadLocals.TOKEN_AUTHENICATORS_TL.set(provider.getTokenAuthenticators());
             ThreadLocals.TOKEN_STORE_TL.set(provider.getTokenStore());
+            ThreadLocals.PASSWORD_HASH_SERVICE_TL.set(provider.getPasswordHashService());
 
             // Initialize the Shiro environment from clustered-app-config
             final Ini ini = AAAIniWebEnvironment.createIniFromClusteredAppConfig(provider.getShiroConfiguration());
@@ -61,6 +62,7 @@ public class KarafIniWebEnvironment extends IniWebEnvironment {
             ThreadLocals.AUTH_SETVICE_TL.remove();
             ThreadLocals.TOKEN_AUTHENICATORS_TL.remove();
             ThreadLocals.TOKEN_STORE_TL.remove();
+            ThreadLocals.PASSWORD_HASH_SERVICE_TL.remove();
         }
     }
 }
index ba62fb187feb6db613682bd3222e138b1a019a3d..3901063386f42abf6cef70c57422c6d2bfba4a19 100644 (file)
@@ -14,6 +14,7 @@ import org.apache.shiro.web.env.MutableWebEnvironment;
 import org.apache.shiro.web.env.WebEnvironment;
 import org.opendaylight.aaa.api.AuthenticationService;
 import org.opendaylight.aaa.api.TokenStore;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cert.api.ICertificateManager;
 import org.opendaylight.aaa.shiro.tokenauthrealm.auth.TokenAuthenticators;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -35,23 +36,27 @@ public class ShiroWebEnvironmentLoaderListener extends EnvironmentLoaderListener
     private final AuthenticationService authenticationService;
     private final TokenAuthenticators tokenAuthenticators;
     private final TokenStore tokenStore;
+    private final PasswordHashService passwordHashService;
 
     public ShiroWebEnvironmentLoaderListener(ShiroConfiguration shiroConfiguration, DataBroker dataBroker,
-            ICertificateManager certificateManager, AuthenticationService authenticationService,
-            TokenAuthenticators tokenAuthenticators, TokenStore tokenStore) {
+                                             ICertificateManager certificateManager,
+                                             AuthenticationService authenticationService,
+                                             TokenAuthenticators tokenAuthenticators, TokenStore tokenStore,
+                                             PasswordHashService passwordHashService) {
         this.shiroConfiguration = shiroConfiguration;
         this.dataBroker = dataBroker;
         this.certificateManager = certificateManager;
         this.authenticationService = authenticationService;
         this.tokenAuthenticators = tokenAuthenticators;
         this.tokenStore = tokenStore;
+        this.passwordHashService = passwordHashService;
         LOG.debug("ShiroWebEnvironmentLoaderListenerImpl created");
     }
 
     @Override
     protected WebEnvironment createEnvironment(ServletContext sc) {
         MutableWebEnvironment environment = new AAAIniWebEnvironment(shiroConfiguration, dataBroker,
-                certificateManager, authenticationService, tokenAuthenticators, tokenStore);
+                certificateManager, authenticationService, tokenAuthenticators, tokenStore, passwordHashService);
 
         // in newer Shiro version, there is a determineWebEnvironment() which should be
         // used instead of createEnvironment() but for 1.3.x we just copy/paste from parent and do:
index 6176a00c0dd87d8e4bc57f4b38b7c3af77acafa4..b38b6302fa0da70f832b04fe47dad9cc9d91abdd 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.aaa.shiro.web.env;
 
 import org.opendaylight.aaa.api.AuthenticationService;
 import org.opendaylight.aaa.api.TokenStore;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
 import org.opendaylight.aaa.cert.api.ICertificateManager;
 import org.opendaylight.aaa.shiro.tokenauthrealm.auth.TokenAuthenticators;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -29,4 +30,6 @@ public interface ThreadLocals {
     ThreadLocal<TokenStore> TOKEN_STORE_TL = new ThreadLocal<>();
 
     ThreadLocal<TokenAuthenticators> TOKEN_AUTHENICATORS_TL = new ThreadLocal<>();
+
+    ThreadLocal<PasswordHashService> PASSWORD_HASH_SERVICE_TL = new ThreadLocal<>();
 }
index 909140b6ee660a7cf3a2e756a5351f354418e4b7..54280861067bf0b7b784677f1e1e50c19147b071 100644 (file)
@@ -20,13 +20,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         default-config-file-name="aaa-datastore-config.xml"
         binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.DatastoreConfig" />
 
+  <reference id="passwordService" interface="org.opendaylight.aaa.api.password.service.PasswordHashService"
+        odl:type="default"/>
+
   <bean id="idmStore" class="org.opendaylight.aaa.datastore.h2.H2Store">
     <argument value="${dbUsername}" />
     <argument value="${dbPassword}" />
+    <argument ref="passwordService" />
   </bean>
 
   <bean id="idmLightProxy" class="org.opendaylight.aaa.shiro.idm.IdmLightProxy">
     <argument ref="idmStore" />
+    <argument ref="passwordService" />
   </bean>
 
   <bean id="authService" class="org.opendaylight.aaa.shiro.tokenauthrealm.auth.AuthenticationManager"/>
@@ -73,6 +78,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <argument ref="datastoreConfig" />
     <argument ref="idmStore" />
     <argument ref="authService" />
+    <argument ref="passwordService" />
   </bean>
 
   <bean id="authenticator" class="org.opendaylight.aaa.authenticator.ODLAuthenticator" />
@@ -89,6 +95,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <argument>
       <bean factory-ref="provider" factory-method="getTokenStore"/>
     </argument>
+    <argument ref="passwordService" />
   </bean>
 
   <reference id="customFilterAdapterConfig"
index 52d3c73a5d0be1e5c5e8bee956a111c7ce241114..c21aa6ad59bd4e253b661c3c86e9955757f1329c 100644 (file)
@@ -22,6 +22,8 @@ import org.opendaylight.aaa.api.model.Domain;
 import org.opendaylight.aaa.api.model.Grant;
 import org.opendaylight.aaa.api.model.Role;
 import org.opendaylight.aaa.api.model.User;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
+import org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService;
 
 public class H2StoreTest {
 
@@ -50,12 +52,13 @@ public class H2StoreTest {
     }
 
     private H2Store h2Store;
+    private PasswordHashService passwordService = new DefaultPasswordHashService();
 
     @Before
     public void before() throws StoreException, SQLException {
         IdmLightSimpleConnectionProvider dbConnectionFactory = new IdmLightSimpleConnectionProvider(
                 new IdmLightConfigBuilder().dbUser("foo").dbPwd("bar").build());
-        UserStore us = new UserStore(dbConnectionFactory);
+        UserStore us = new UserStore(dbConnectionFactory, passwordService);
         us.dbClean();
         DomainStore ds = new DomainStore(dbConnectionFactory);
         ds.dbClean();
@@ -64,7 +67,7 @@ public class H2StoreTest {
         GrantStore gs = new GrantStore(dbConnectionFactory);
         gs.dbClean();
 
-        h2Store = new H2Store("foo", "bar");
+        h2Store = new H2Store("foo", "bar", passwordService);
     }
 
     @Test
@@ -87,7 +90,8 @@ public class H2StoreTest {
 
     @Test
     public void testCreateUser() throws StoreException {
-        User user = h2Store.createUser("test", "pass", "domain", "desc", "email", true, "SALT");
+        User user = h2Store.createUser("test", "pass", "domain", "desc",
+                "email",true, "SALT");
         Assert.assertEquals(true, user != null);
     }
 
@@ -95,7 +99,8 @@ public class H2StoreTest {
     public void testCreateGrant() throws StoreException {
         Domain domain = h2Store.createDomain("sdn", true);
         Role role = h2Store.createRole("temp", "temp domain", "Temp Testing role");
-        User user = h2Store.createUser("test", "pass", "domain", "desc", "email", true, "SALT");
+        User user = h2Store.createUser("test", "pass", "domain", "desc",
+                "email", true, "SALT");
         Grant grant = h2Store.createGrant(domain.getDomainid(), user.getUserid(), role.getRoleid());
         Assert.assertEquals(true, grant != null);
     }
@@ -103,9 +108,11 @@ public class H2StoreTest {
     @Test
     public void testUpdatingUserEmail() throws StoreException {
         UserStore us = new UserStore(
-                new IdmLightSimpleConnectionProvider(new IdmLightConfigBuilder().dbUser("foo").dbPwd("bar").build()));
+                new IdmLightSimpleConnectionProvider(
+                        new IdmLightConfigBuilder().dbUser("foo").dbPwd("bar").build()), passwordService);
         Domain domain = h2Store.createDomain("sdn", true);
-        User user = h2Store.createUser("test", "pass", domain.getDomainid(), "desc", "email", true, "SALT");
+        User user = h2Store.createUser("test", "pass", domain.getDomainid(), "desc",
+                "email", true, "SALT");
 
         user.setName("test");
         user = us.putUser(user);
index 57b2ca90eb58167196dc3b27efd5289c1447b6ef..5422d9d1fb42772fecdd877636cd049b940af68d 100644 (file)
@@ -21,6 +21,7 @@ import java.sql.Statement;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService;
 
 public class UserStoreTest {
 
@@ -28,7 +29,8 @@ public class UserStoreTest {
 
     private final ConnectionProvider connectionFactoryMock = () -> connectionMock;
 
-    private final UserStore userStoreUnderTest = new UserStore(connectionFactoryMock);
+    private final UserStore userStoreUnderTest = new UserStore(connectionFactoryMock,
+            new DefaultPasswordHashService());
 
     @Test
     public void getUsersTest() throws SQLException, Exception {
index 1afafc2d41f4a6d1502c2d6c7e17d52f327ad7e1..938b74b89d1143cd0bbaf759e71fd9a0c0bc4b4b 100644 (file)
@@ -16,13 +16,14 @@ import org.mockito.Mockito;
 import org.opendaylight.aaa.api.IDMStoreException;
 import org.opendaylight.aaa.api.IIDMStore;
 import org.opendaylight.aaa.api.PasswordCredentials;
-import org.opendaylight.aaa.api.SHA256Calculator;
 import org.opendaylight.aaa.api.model.Domain;
 import org.opendaylight.aaa.api.model.Grant;
 import org.opendaylight.aaa.api.model.Grants;
 import org.opendaylight.aaa.api.model.Role;
 import org.opendaylight.aaa.api.model.User;
 import org.opendaylight.aaa.api.model.Users;
+import org.opendaylight.aaa.api.password.service.PasswordHashService;
+import org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService;
 import org.opendaylight.aaa.shiro.idm.IdmLightProxy;
 
 /*
@@ -31,6 +32,7 @@ import org.opendaylight.aaa.shiro.idm.IdmLightProxy;
 public class PasswordHashTest {
 
     private IIDMStore store;
+    private PasswordHashService passwordService = new DefaultPasswordHashService();
 
     @Before
     public void before() throws IDMStoreException {
@@ -47,7 +49,7 @@ public class PasswordHashTest {
         user.setUserid(creds.username());
         user.setDomainid("sdn");
         user.setSalt("ABCD");
-        user.setPassword(SHA256Calculator.getSHA256(creds.password(), user.getSalt()));
+        user.setPassword(passwordService.getPasswordHash(creds.password(), user.getSalt()).getHashedPassword());
         List<User> lu = new LinkedList<>();
         lu.add(user);
         Users users = new Users();
@@ -71,7 +73,7 @@ public class PasswordHashTest {
 
     @Test
     public void testPasswordHash() {
-        IdmLightProxy proxy = new IdmLightProxy(store);
+        IdmLightProxy proxy = new IdmLightProxy(store, passwordService);
         proxy.authenticate(new Creds());
     }
 
index 3fc5c4758d4e4fe92eb8e65ea0834b07640ef6da..8c3ab98c72ab0e0caa38ff1025003d9d7233edaf 100644 (file)
@@ -17,6 +17,7 @@ import org.glassfish.jersey.test.JerseyTest;
 import org.junit.Before;
 import org.opendaylight.aaa.api.IIDMStore;
 import org.opendaylight.aaa.api.StoreBuilder;
+import org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService;
 import org.opendaylight.aaa.provider.GsonProvider;
 import org.opendaylight.aaa.shiro.idm.IdmLightApplication;
 import org.opendaylight.aaa.shiro.idm.IdmLightProxy;
@@ -28,7 +29,8 @@ public abstract class HandlerTest extends JerseyTest {
     @Override
     protected Application configure() {
         testStore = new IDMTestStore();
-        return ResourceConfig.forApplication(new IdmLightApplication(testStore, new IdmLightProxy(testStore)));
+        return ResourceConfig.forApplication(new IdmLightApplication(testStore,
+                new IdmLightProxy(testStore, new DefaultPasswordHashService())));
     }
 
     @Override
index dca7674c8354b09d65e268c14654db7411e97844..61728c5c8b8e0d0accafc730052e7bba9c9a7836 100644 (file)
     </dependencyManagement>
 
     <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>odl-aaa-password-service</artifactId>
+            <version>${project.version}</version>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
+
         <!-- OSGI -->
         <dependency>
             <groupId>org.apache.felix</groupId>
@@ -66,7 +74,7 @@
         <dependency>
             <groupId>org.opendaylight.aaa</groupId>
             <artifactId>odl-aaa-web</artifactId>
-            <version>0.8.0-SNAPSHOT</version>
+            <version>${project.version}</version>
             <classifier>features</classifier>
             <type>xml</type>
         </dependency>
index d48ae26ea57a33f8116f72b4d38345c6f6618431..1620e090c8e16cb94195f20c95143287016061d5 100644 (file)
@@ -14,6 +14,9 @@
         <configfile finalname="etc/opendaylight/datastore/initial/config/aaa-datastore-config.xml">
             mvn:org.opendaylight.aaa/aaa-shiro/${project.version}/xml/aaa-datastore-config
         </configfile>
+        <configfile finalname="etc/opendaylight/datastore/initial/config/aaa-password-service-config.xml">
+            mvn:org.opendaylight.aaa/aaa-password-service-impl/${project.version}/xml/aaa-password-service-config
+        </configfile>
         <configfile finalname="bin/idmtool">
             mvn:org.opendaylight.aaa/aaa-shiro/${project.version}/py/idmtool
         </configfile>