From 3aaefa736ea182afe22af6651e5bbb7cc4f84512 Mon Sep 17 00:00:00 2001 From: Ryan Goulding Date: Thu, 17 May 2018 16:13:26 -0400 Subject: [PATCH] adjust to use password-service 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 --- aaa-cli-jar/pom.xml | 20 +++++++++++++++++++ .../jar/StandaloneCommandLineInterface.java | 11 ++++++---- .../aaa/cli/AaaCliAbstractCommand.java | 9 ++++++++- .../aaa/cli/dmstore/AddDomain.java | 5 +++-- .../aaa/cli/dmstore/AddGrant.java | 5 +++-- .../opendaylight/aaa/cli/dmstore/AddRole.java | 5 +++-- .../opendaylight/aaa/cli/dmstore/AddUser.java | 5 +++-- .../aaa/cli/dmstore/ChangeUserPassword.java | 13 ++++++++---- .../aaa/cli/dmstore/ListODLDomains.java | 5 +++-- .../aaa/cli/dmstore/ListODLRoles.java | 5 +++-- .../aaa/cli/dmstore/ListODLUsers.java | 5 +++-- .../aaa/cli/dmstore/RemoveDomain.java | 4 +++- .../aaa/cli/dmstore/RemoveGrant.java | 4 +++- .../aaa/cli/dmstore/RemoveRole.java | 4 +++- .../aaa/cli/dmstore/RemoveUser.java | 4 +++- .../aaa/cli/utils/DataStoreUtils.java | 13 +++++++----- .../org/opendaylight/blueprint/commands.xml | 20 +++++++++++++++++++ .../cli/test/AaaCliAbstractCommandTest.java | 2 +- aaa-password-service/impl/pom.xml | 20 ++++++++++++++++++- .../service/DefaultPasswordHashService.java | 13 ++++++++---- .../blueprint/password-service-blueprint.xml | 2 +- aaa-shiro/impl/pom.xml | 9 +++++++++ .../opendaylight/aaa/AAAShiroProvider.java | 10 +++++++++- .../aaa/datastore/h2/H2Store.java | 9 +++++---- .../aaa/datastore/h2/UserStore.java | 19 ++++++++++++------ .../aaa/shiro/idm/IdmLightProxy.java | 10 ++++++---- .../aaa/shiro/realm/MdsalRealm.java | 7 ++++--- .../shiro/web/env/AAAIniWebEnvironment.java | 10 ++++++++-- .../shiro/web/env/KarafIniWebEnvironment.java | 2 ++ .../ShiroWebEnvironmentLoaderListener.java | 11 +++++++--- .../aaa/shiro/web/env/ThreadLocals.java | 3 +++ .../opendaylight/blueprint/impl-blueprint.xml | 7 +++++++ .../aaa/datastore/h2/H2StoreTest.java | 19 ++++++++++++------ .../aaa/datastore/h2/UserStoreTest.java | 4 +++- .../idm/persistence/PasswordHashTest.java | 8 +++++--- .../aaa/shiro/idm/rest/test/HandlerTest.java | 4 +++- features/odl-aaa-shiro/pom.xml | 10 +++++++++- .../src/main/feature/feature.xml | 3 +++ 38 files changed, 245 insertions(+), 74 deletions(-) diff --git a/aaa-cli-jar/pom.xml b/aaa-cli-jar/pom.xml index 682fb87fd..4565a7f04 100644 --- a/aaa-cli-jar/pom.xml +++ b/aaa-cli-jar/pom.xml @@ -85,6 +85,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL org.opendaylight.yangtools testutils + + org.opendaylight.aaa + aaa-password-service-api + + + org.opendaylight.aaa + aaa-password-service-impl + @@ -152,6 +160,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL org/h2/constraint/** + + org.opendaylight.aaa:aaa-password-service-api + + org/opendaylight/** + + + + org.opendaylight.aaa:aaa-password-service-impl + + org/opendaylight/** + + diff --git a/aaa-cli-jar/src/main/java/org/opendaylight/aaa/cli/jar/StandaloneCommandLineInterface.java b/aaa-cli-jar/src/main/java/org/opendaylight/aaa/cli/jar/StandaloneCommandLineInterface.java index b33e6356f..3de3f55bf 100644 --- a/aaa-cli-jar/src/main/java/org/opendaylight/aaa/cli/jar/StandaloneCommandLineInterface.java +++ b/aaa-cli-jar/src/main/java/org/opendaylight/aaa/cli/jar/StandaloneCommandLineInterface.java @@ -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()); } } diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/AaaCliAbstractCommand.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/AaaCliAbstractCommand.java index 92fb91142..d9831b556 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/AaaCliAbstractCommand.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/AaaCliAbstractCommand.java @@ -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); diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddDomain.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddDomain.java index a42637cb0..2fe7e554c 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddDomain.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddDomain.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddGrant.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddGrant.java index 95ea9ff69..e9074d82a 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddGrant.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddGrant.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddRole.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddRole.java index 9506b5878..99ccf1a19 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddRole.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddRole.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddUser.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddUser.java index ac979f043..59efb3cd5 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddUser.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/AddUser.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ChangeUserPassword.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ChangeUserPassword.java index b4b35d7f0..3959babdc 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ChangeUserPassword.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ChangeUserPassword.java @@ -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); diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLDomains.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLDomains.java index 183700bd1..b64030419 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLDomains.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLDomains.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLRoles.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLRoles.java index 4f63cc266..b21f92b6b 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLRoles.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLRoles.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLUsers.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLUsers.java index ba43df671..144ff3fba 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLUsers.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/ListODLUsers.java @@ -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 diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveDomain.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveDomain.java index 1881021bd..ba5611fef 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveDomain.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveDomain.java @@ -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; } diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveGrant.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveGrant.java index dd603c29f..fd79193e4 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveGrant.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveGrant.java @@ -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; } diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveRole.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveRole.java index 077d3fe2f..5da16d3f3 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveRole.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveRole.java @@ -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; } diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveUser.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveUser.java index c65e7d38b..16b533ffe 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveUser.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/dmstore/RemoveUser.java @@ -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; } diff --git a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/utils/DataStoreUtils.java b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/utils/DataStoreUtils.java index b7a0e758a..98207641a 100644 --- a/aaa-cli/src/main/java/org/opendaylight/aaa/cli/utils/DataStoreUtils.java +++ b/aaa-cli/src/main/java/org/opendaylight/aaa/cli/utils/DataStoreUtils.java @@ -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 grants = identityStore.getGrants(usr.getUserid()).getGrants(); if (grants != null && !grants.isEmpty()) { final String adminRoleId = getRoleId(identityStore, ADMIN_ROLE); diff --git a/aaa-cli/src/main/resources/org/opendaylight/blueprint/commands.xml b/aaa-cli/src/main/resources/org/opendaylight/blueprint/commands.xml index 069e1cb2d..b7a50aa29 100644 --- a/aaa-cli/src/main/resources/org/opendaylight/blueprint/commands.xml +++ b/aaa-cli/src/main/resources/org/opendaylight/blueprint/commands.xml @@ -6,106 +6,126 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/aaa-cli/src/test/java/org/opendaylight/aaa/cli/test/AaaCliAbstractCommandTest.java b/aaa-cli/src/test/java/org/opendaylight/aaa/cli/test/AaaCliAbstractCommandTest.java index fdc428c42..5fc1dd865 100644 --- a/aaa-cli/src/test/java/org/opendaylight/aaa/cli/test/AaaCliAbstractCommandTest.java +++ b/aaa-cli/src/test/java/org/opendaylight/aaa/cli/test/AaaCliAbstractCommandTest.java @@ -34,7 +34,7 @@ public class AaaCliAbstractCommandTest { class TestAaaCliAbstractCommand extends AaaCliAbstractCommand { TestAaaCliAbstractCommand() { - super(); + super(null); } @Override diff --git a/aaa-password-service/impl/pom.xml b/aaa-password-service/impl/pom.xml index 0cfdcf93f..e24015afc 100644 --- a/aaa-password-service/impl/pom.xml +++ b/aaa-password-service/impl/pom.xml @@ -37,6 +37,25 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + org.apache.felix + maven-bundle-plugin + true + + + + + org.opendaylight.aaa.impl.password.service.DefaultPasswordHashService + + + + org.codehaus.mojo build-helper-maven-plugin @@ -49,7 +68,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html - ${project.build.directory}/classes/initial/aaa-password-service-config.xml xml diff --git a/aaa-password-service/impl/src/main/java/org/opendaylight/aaa/impl/password/service/DefaultPasswordHashService.java b/aaa-password-service/impl/src/main/java/org/opendaylight/aaa/impl/password/service/DefaultPasswordHashService.java index 151e15055..90faa3230 100644 --- a/aaa-password-service/impl/src/main/java/org/opendaylight/aaa/impl/password/service/DefaultPasswordHashService.java +++ b/aaa-password-service/impl/src/main/java/org/opendaylight/aaa/impl/password/service/DefaultPasswordHashService.java @@ -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 numIterationsOptional = Optional.ofNullable(passwordServiceConfig.getIterations()); setNumIterations(numIterationsOptional); @@ -39,9 +47,6 @@ public class DefaultPasswordHashService implements PasswordHashService { final Optional privateSaltOptional = Optional.ofNullable(passwordServiceConfig.getPrivateSalt()); setPrivateSalt(privateSaltOptional); - - hashService.setRandomNumberGenerator(new SecureRandomNumberGenerator()); - hashService.setGeneratePublicSalt(true); } private void setNumIterations(final Optional numIterationsOptional) { diff --git a/aaa-password-service/impl/src/main/resources/org/opendaylight/blueprint/password-service-blueprint.xml b/aaa-password-service/impl/src/main/resources/org/opendaylight/blueprint/password-service-blueprint.xml index 752a1b0b6..019493c03 100644 --- a/aaa-password-service/impl/src/main/resources/org/opendaylight/blueprint/password-service-blueprint.xml +++ b/aaa-password-service/impl/src/main/resources/org/opendaylight/blueprint/password-service-blueprint.xml @@ -18,7 +18,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html - diff --git a/aaa-shiro/impl/pom.xml b/aaa-shiro/impl/pom.xml index aa935377c..b076fb9de 100644 --- a/aaa-shiro/impl/pom.xml +++ b/aaa-shiro/impl/pom.xml @@ -90,6 +90,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html org.opendaylight.aaa aaa-filterchain + + org.opendaylight.aaa + aaa-password-service-api + org.osgi org.osgi.compendium @@ -176,6 +180,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html com.google.truth truth + + org.opendaylight.aaa + aaa-password-service-impl + test + diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/AAAShiroProvider.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/AAAShiroProvider.java index 42a7cda6e..3e9bf7ffa 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/AAAShiroProvider.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/AAAShiroProvider.java @@ -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; + } } diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/H2Store.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/H2Store.java index 78334bd76..a6abdc98d 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/H2Store.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/H2Store.java @@ -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); } diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/UserStore.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/UserStore.java index 8280b6805..85eecaab1 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/UserStore.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/datastore/h2/UserStore.java @@ -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 { 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 { 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 { 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 { 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 { 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 = ?"; diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/idm/IdmLightProxy.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/idm/IdmLightProxy.java index 116f7a99c..65db8e67f 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/idm/IdmLightProxy.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/idm/IdmLightProxy.java @@ -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, IdMSe private final Map> 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, 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()) { diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/realm/MdsalRealm.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/realm/MdsalRealm.java index 3d4db766e..8a7707342 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/realm/MdsalRealm.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/realm/MdsalRealm.java @@ -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()); diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/AAAIniWebEnvironment.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/AAAIniWebEnvironment.java index 55e78e2b6..5ac0bd441 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/AAAIniWebEnvironment.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/AAAIniWebEnvironment.java @@ -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(); } } } diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java index b06e6fddb..f88924900 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java @@ -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(); } } } diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ShiroWebEnvironmentLoaderListener.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ShiroWebEnvironmentLoaderListener.java index ba62fb187..390106338 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ShiroWebEnvironmentLoaderListener.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ShiroWebEnvironmentLoaderListener.java @@ -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: diff --git a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ThreadLocals.java b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ThreadLocals.java index 6176a00c0..b38b6302f 100644 --- a/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ThreadLocals.java +++ b/aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/web/env/ThreadLocals.java @@ -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 TOKEN_STORE_TL = new ThreadLocal<>(); ThreadLocal TOKEN_AUTHENICATORS_TL = new ThreadLocal<>(); + + ThreadLocal PASSWORD_HASH_SERVICE_TL = new ThreadLocal<>(); } diff --git a/aaa-shiro/impl/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/aaa-shiro/impl/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml index 909140b6e..542808610 100644 --- a/aaa-shiro/impl/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml +++ b/aaa-shiro/impl/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml @@ -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" /> + + + + @@ -73,6 +78,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + @@ -89,6 +95,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + connectionMock; - private final UserStore userStoreUnderTest = new UserStore(connectionFactoryMock); + private final UserStore userStoreUnderTest = new UserStore(connectionFactoryMock, + new DefaultPasswordHashService()); @Test public void getUsersTest() throws SQLException, Exception { diff --git a/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/persistence/PasswordHashTest.java b/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/persistence/PasswordHashTest.java index 1afafc2d4..938b74b89 100644 --- a/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/persistence/PasswordHashTest.java +++ b/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/persistence/PasswordHashTest.java @@ -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 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()); } diff --git a/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/rest/test/HandlerTest.java b/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/rest/test/HandlerTest.java index 3fc5c4758..8c3ab98c7 100644 --- a/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/rest/test/HandlerTest.java +++ b/aaa-shiro/impl/src/test/java/org/opendaylight/aaa/shiro/idm/rest/test/HandlerTest.java @@ -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 diff --git a/features/odl-aaa-shiro/pom.xml b/features/odl-aaa-shiro/pom.xml index dca7674c8..61728c5c8 100644 --- a/features/odl-aaa-shiro/pom.xml +++ b/features/odl-aaa-shiro/pom.xml @@ -44,6 +44,14 @@ + + org.opendaylight.aaa + odl-aaa-password-service + ${project.version} + features + xml + + org.apache.felix @@ -66,7 +74,7 @@ org.opendaylight.aaa odl-aaa-web - 0.8.0-SNAPSHOT + ${project.version} features xml diff --git a/features/odl-aaa-shiro/src/main/feature/feature.xml b/features/odl-aaa-shiro/src/main/feature/feature.xml index d48ae26ea..1620e090c 100644 --- a/features/odl-aaa-shiro/src/main/feature/feature.xml +++ b/features/odl-aaa-shiro/src/main/feature/feature.xml @@ -14,6 +14,9 @@ mvn:org.opendaylight.aaa/aaa-shiro/${project.version}/xml/aaa-datastore-config + + mvn:org.opendaylight.aaa/aaa-password-service-impl/${project.version}/xml/aaa-password-service-config + mvn:org.opendaylight.aaa/aaa-shiro/${project.version}/py/idmtool -- 2.36.6