killbill-memoizeit

util: make KillbillCredentialsMatcher respect KillbillConfigSource This

10/7/2015 9:38:23 AM

Details

diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
index 8955201..85b17d9 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
@@ -27,6 +27,7 @@ import org.apache.shiro.authc.SimpleAuthenticationInfo;
 import org.apache.shiro.codec.Base64;
 import org.apache.shiro.realm.jdbc.JdbcRealm;
 import org.apache.shiro.util.ByteSource;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.killbill.billing.util.security.shiro.KillbillCredentialsMatcher;
 
 /**
@@ -37,11 +38,13 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
     private static final String KILLBILL_AUTHENTICATION_QUERY = "select api_secret, api_salt from tenants where api_key = ?";
 
     private final DataSource dataSource;
+    private final SecurityConfig securityConfig;
 
-    public KillbillJdbcTenantRealm(final DataSource dataSource) {
+    public KillbillJdbcTenantRealm(final DataSource dataSource, final SecurityConfig securityConfig) {
         super();
 
         this.dataSource = dataSource;
+        this.securityConfig = securityConfig;
 
         configureSecurity();
         configureQueries();
@@ -61,7 +64,7 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
 
     private void configureSecurity() {
         setSaltStyle(SaltStyle.COLUMN);
-        setCredentialsMatcher(KillbillCredentialsMatcher.getCredentialsMatcher());
+        setCredentialsMatcher(KillbillCredentialsMatcher.getCredentialsMatcher(securityConfig));
     }
 
     private void configureQueries() {
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/security/TenantFilter.java b/profiles/killbill/src/main/java/org/killbill/billing/server/security/TenantFilter.java
index 4fb769e..97e2bed 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/security/TenantFilter.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/security/TenantFilter.java
@@ -44,6 +44,7 @@ import org.killbill.billing.server.modules.KillbillPlatformModule;
 import org.killbill.billing.tenant.api.Tenant;
 import org.killbill.billing.tenant.api.TenantApiException;
 import org.killbill.billing.tenant.api.TenantUserApi;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -59,6 +60,8 @@ public class TenantFilter implements Filter {
 
     @Inject
     protected TenantUserApi tenantUserApi;
+    @Inject
+    protected SecurityConfig securityConfig;
 
     @Inject
     @Named(KillbillPlatformModule.SHIRO_DATA_SOURCE_ID_NAMED)
@@ -68,7 +71,7 @@ public class TenantFilter implements Filter {
 
     @Override
     public void init(final FilterConfig filterConfig) throws ServletException {
-        final Realm killbillJdbcTenantRealm = new KillbillJdbcTenantRealm(dataSource);
+        final Realm killbillJdbcTenantRealm = new KillbillJdbcTenantRealm(dataSource, securityConfig);
         // We use Shiro to verify the api credentials - but the Shiro Subject is only used for RBAC
         modularRealmAuthenticator = new ModularRealmAuthenticator();
         modularRealmAuthenticator.setRealms(ImmutableList.<Realm>of(killbillJdbcTenantRealm));
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
index bdfaa5d..fa48420 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
@@ -54,6 +54,7 @@ import org.killbill.billing.server.listeners.KillbillGuiceListener;
 import org.killbill.billing.server.modules.KillbillServerModule;
 import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.config.PaymentConfig;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.killbill.bus.api.PersistentBus;
 import org.killbill.commons.jdbi.guice.DaoConfig;
 import org.skife.config.ConfigurationObjectFactory;
@@ -96,6 +97,9 @@ public class TestJaxrsBase extends KillbillClient {
     @Named(KillbillServerModule.SHIRO_DATA_SOURCE_ID)
     protected DataSource shiroDataSource;
 
+    @Inject
+    protected SecurityConfig securityConfig;
+
     protected DaoConfig daoConfig;
     protected KillbillServerConfig serverConfig;
 
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/server/security/TestKillbillJdbcTenantRealm.java b/profiles/killbill/src/test/java/org/killbill/billing/server/security/TestKillbillJdbcTenantRealm.java
index b3899fd..a82fe1e 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/server/security/TestKillbillJdbcTenantRealm.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/server/security/TestKillbillJdbcTenantRealm.java
@@ -49,7 +49,7 @@ public class TestKillbillJdbcTenantRealm extends TestJaxrsBase {
         super.beforeMethod();
 
         // Create the tenant
-        final DefaultTenantDao tenantDao = new DefaultTenantDao(dbi, clock, cacheControllerDispatcher, new DefaultNonEntityDao(dbi));
+        final DefaultTenantDao tenantDao = new DefaultTenantDao(dbi, clock, cacheControllerDispatcher, new DefaultNonEntityDao(dbi), securityConfig);
         tenant = new DefaultTenant(UUID.randomUUID(), null, null, UUID.randomUUID().toString(),
                                    UUID.randomUUID().toString(), UUID.randomUUID().toString());
         tenantDao.create(new TenantModelDao(tenant), internalCallContext);
@@ -60,7 +60,7 @@ public class TestKillbillJdbcTenantRealm extends TestJaxrsBase {
         dbConfig.setUsername(helper.getUsername());
         dbConfig.setPassword(helper.getPassword());
 
-        final KillbillJdbcTenantRealm jdbcRealm = new KillbillJdbcTenantRealm(shiroDataSource);
+        final KillbillJdbcTenantRealm jdbcRealm = new KillbillJdbcTenantRealm(shiroDataSource, securityConfig);
         jdbcRealm.setDataSource(new HikariDataSource(dbConfig));
 
         securityManager = new DefaultSecurityManager(jdbcRealm);
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java
index 14ada6f..4d929d4 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java
@@ -1,7 +1,9 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
  *
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
  * (the "License"); you may not use this file except in compliance with the
  * License.  You may obtain a copy of the License at:
  *
@@ -35,6 +37,7 @@ import org.killbill.billing.tenant.api.TenantApiException;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
 import org.killbill.billing.util.UUIDs;
 import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.killbill.billing.util.dao.NonEntityDao;
 import org.killbill.billing.util.entity.dao.EntityDaoBase;
 import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
@@ -56,9 +59,12 @@ public class DefaultTenantDao extends EntityDaoBase<TenantModelDao, Tenant, Tena
 
     private final RandomNumberGenerator rng = new SecureRandomNumberGenerator();
 
+    private final SecurityConfig securityConfig;
+
     @Inject
-    public DefaultTenantDao(final IDBI dbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao) {
+    public DefaultTenantDao(final IDBI dbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao, final SecurityConfig securityConfig) {
         super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao), TenantSqlDao.class);
+        this.securityConfig = securityConfig;
     }
 
     @Override
@@ -82,7 +88,7 @@ public class DefaultTenantDao extends EntityDaoBase<TenantModelDao, Tenant, Tena
         final ByteSource salt = rng.nextBytes();
         // Hash the plain-text password with the random salt and multiple iterations and then Base64-encode the value (requires less space than Hex)
         final String hashedPasswordBase64 = new SimpleHash(KillbillCredentialsMatcher.HASH_ALGORITHM_NAME,
-                                                           entity.getApiSecret(), salt, KillbillCredentialsMatcher.HASH_ITERATIONS).toBase64();
+                                                           entity.getApiSecret(), salt, securityConfig.getShiroNbHashIterations()).toBase64();
 
         transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
             @Override
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java b/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java
index d23e86a..112e3ba 100644
--- a/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java
+++ b/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java
@@ -45,11 +45,11 @@ public class TestDefaultTenantDao extends TenantTestSuiteWithEmbeddedDb {
 
         // Good combo
         final AuthenticationToken goodToken = new UsernamePasswordToken(tenant.getApiKey(), tenant.getApiSecret());
-        Assert.assertTrue(KillbillCredentialsMatcher.getCredentialsMatcher().doCredentialsMatch(goodToken, authenticationInfo));
+        Assert.assertTrue(KillbillCredentialsMatcher.getCredentialsMatcher(securityConfig).doCredentialsMatch(goodToken, authenticationInfo));
 
         // Bad combo
         final AuthenticationToken badToken = new UsernamePasswordToken(tenant.getApiKey(), tenant.getApiSecret() + "T");
-        Assert.assertFalse(KillbillCredentialsMatcher.getCredentialsMatcher().doCredentialsMatch(badToken, authenticationInfo));
+        Assert.assertFalse(KillbillCredentialsMatcher.getCredentialsMatcher(securityConfig).doCredentialsMatch(badToken, authenticationInfo));
     }
 
     @Test(groups = "slow")
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/glue/TestTenantModuleWithEmbeddedDB.java b/tenant/src/test/java/org/killbill/billing/tenant/glue/TestTenantModuleWithEmbeddedDB.java
index c2acf95..0bae0d1 100644
--- a/tenant/src/test/java/org/killbill/billing/tenant/glue/TestTenantModuleWithEmbeddedDB.java
+++ b/tenant/src/test/java/org/killbill/billing/tenant/glue/TestTenantModuleWithEmbeddedDB.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
  *
  * The Billing Project licenses this file to you under the Apache License, version 2.0
  * (the "License"); you may not use this file except in compliance with the
@@ -21,6 +21,8 @@ package org.killbill.billing.tenant.glue;
 import org.killbill.billing.GuicyKillbillTestWithEmbeddedDBModule;
 import org.killbill.billing.platform.api.KillbillConfigSource;
 import org.killbill.billing.util.glue.NonEntityDaoModule;
+import org.killbill.billing.util.glue.SecurityModule;
+import org.killbill.billing.util.glue.TestUtilModuleNoDB.ShiroModuleNoDB;
 
 public class TestTenantModuleWithEmbeddedDB extends TestTenantModule {
 
@@ -34,5 +36,7 @@ public class TestTenantModuleWithEmbeddedDB extends TestTenantModule {
 
         install(new GuicyKillbillTestWithEmbeddedDBModule(configSource));
         install(new NonEntityDaoModule(configSource));
+        install(new SecurityModule(configSource));
+        install(new ShiroModuleNoDB(configSource));
     }
 }
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java b/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java
index 48b6287..2c4f78f 100644
--- a/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java
+++ b/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java
@@ -1,7 +1,9 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
  *
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
  * (the "License"); you may not use this file except in compliance with the
  * License.  You may obtain a copy of the License at:
  *
@@ -18,18 +20,17 @@ package org.killbill.billing.tenant;
 
 import javax.inject.Named;
 
+import org.killbill.billing.GuicyKillbillTestSuiteWithEmbeddedDB;
 import org.killbill.billing.tenant.api.TenantUserApi;
-import org.killbill.billing.tenant.dao.NoCachingTenantBroadcastDao;
+import org.killbill.billing.tenant.dao.DefaultTenantDao;
 import org.killbill.billing.tenant.dao.TenantBroadcastDao;
 import org.killbill.billing.tenant.glue.DefaultTenantModule;
+import org.killbill.billing.tenant.glue.TestTenantModuleWithEmbeddedDB;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 
-import org.killbill.billing.GuicyKillbillTestSuiteWithEmbeddedDB;
-import org.killbill.billing.tenant.dao.DefaultTenantDao;
-import org.killbill.billing.tenant.glue.TestTenantModuleWithEmbeddedDB;
-
 import com.google.inject.Guice;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -49,6 +50,9 @@ public class TenantTestSuiteWithEmbeddedDb extends GuicyKillbillTestSuiteWithEmb
     @Inject
     protected TenantBroadcastDao tenantBroadcastDao;
 
+    @Inject
+    protected SecurityConfig securityConfig;
+
     @BeforeClass(groups = "slow")
     protected void beforeClass() throws Exception {
         final Injector injector = Guice.createInjector(new TestTenantModuleWithEmbeddedDB(configSource));
diff --git a/util/src/main/java/org/killbill/billing/util/config/SecurityConfig.java b/util/src/main/java/org/killbill/billing/util/config/SecurityConfig.java
index d53b6c6..3b2382d 100644
--- a/util/src/main/java/org/killbill/billing/util/config/SecurityConfig.java
+++ b/util/src/main/java/org/killbill/billing/util/config/SecurityConfig.java
@@ -28,6 +28,11 @@ public interface SecurityConfig extends KillbillConfig {
     @Description("Path to the shiro.ini file (classpath, url or file resource)")
     public String getShiroResourcePath();
 
+    @Config("org.killbill.security.shiroNbHashIterations")
+    @Default("200000")
+    @Description("Sets the number of times submitted credentials will be hashed before comparing to the credentials stored in the system")
+    public Integer getShiroNbHashIterations();
+
     // LDAP Realm
 
     @Config("org.killbill.security.ldap.userDnTemplate")
diff --git a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java
index 92cc4f9..28b9ca3 100644
--- a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java
+++ b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/DefaultUserDao.java
@@ -28,6 +28,7 @@ import org.apache.shiro.util.ByteSource;
 import org.joda.time.DateTime;
 import org.killbill.billing.ErrorCode;
 import org.killbill.billing.security.SecurityApiException;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.killbill.billing.util.security.shiro.KillbillCredentialsMatcher;
 import org.killbill.clock.Clock;
 import org.killbill.commons.jdbi.mapper.LowerToCamelBeanMapperFactory;
@@ -43,17 +44,19 @@ import com.google.common.collect.Iterables;
 public class DefaultUserDao implements UserDao {
 
     private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator();
+
     private final IDBI dbi;
     private final Clock clock;
+    private final SecurityConfig securityConfig;
 
     @Inject
-    public DefaultUserDao(final IDBI dbi, final Clock clock) {
+    public DefaultUserDao(final IDBI dbi, final Clock clock, final SecurityConfig securityConfig) {
         this.dbi = dbi;
         this.clock = clock;
+        this.securityConfig = securityConfig;
         ((DBI) dbi).registerMapper(new LowerToCamelBeanMapperFactory(UserModelDao.class));
         ((DBI) dbi).registerMapper(new LowerToCamelBeanMapperFactory(UserRolesModelDao.class));
         ((DBI) dbi).registerMapper(new LowerToCamelBeanMapperFactory(RolesPermissionsModelDao.class));
-
     }
 
     @Override
@@ -61,7 +64,7 @@ public class DefaultUserDao implements UserDao {
 
         final ByteSource salt = rng.nextBytes();
         final String hashedPasswordBase64 = new SimpleHash(KillbillCredentialsMatcher.HASH_ALGORITHM_NAME,
-                                                           password, salt.toBase64(), KillbillCredentialsMatcher.HASH_ITERATIONS).toBase64();
+                                                           password, salt.toBase64(), securityConfig.getShiroNbHashIterations()).toBase64();
 
         final DateTime createdDate = clock.getUTCNow();
         dbi.inTransaction(new TransactionCallback<Void>() {
@@ -136,7 +139,7 @@ public class DefaultUserDao implements UserDao {
 
         final ByteSource salt = rng.nextBytes();
         final String hashedPasswordBase64 = new SimpleHash(KillbillCredentialsMatcher.HASH_ALGORITHM_NAME,
-                                                           password, salt.toBase64(), KillbillCredentialsMatcher.HASH_ITERATIONS).toBase64();
+                                                           password, salt.toBase64(), securityConfig.getShiroNbHashIterations()).toBase64();
 
         dbi.inTransaction(new TransactionCallback<Void>() {
             @Override
diff --git a/util/src/main/java/org/killbill/billing/util/security/shiro/KillbillCredentialsMatcher.java b/util/src/main/java/org/killbill/billing/util/security/shiro/KillbillCredentialsMatcher.java
index 7b5bc12..1830226 100644
--- a/util/src/main/java/org/killbill/billing/util/security/shiro/KillbillCredentialsMatcher.java
+++ b/util/src/main/java/org/killbill/billing/util/security/shiro/KillbillCredentialsMatcher.java
@@ -1,7 +1,9 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
  *
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
  * (the "License"); you may not use this file except in compliance with the
  * License.  You may obtain a copy of the License at:
  *
@@ -19,23 +21,21 @@ package org.killbill.billing.util.security.shiro;
 import org.apache.shiro.authc.credential.CredentialsMatcher;
 import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
 import org.apache.shiro.crypto.hash.Sha512Hash;
+import org.killbill.billing.util.config.SecurityConfig;
 
 public class KillbillCredentialsMatcher {
 
-    public static final String KILLBILL_TENANT_HASH_ITERATIONS_PROPERTY = "org.killbill.server.multitenant.hash_iterations";
-
     // See http://www.stormpath.com/blog/strong-password-hashing-apache-shiro and https://issues.apache.org/jira/browse/SHIRO-290
     public static final String HASH_ALGORITHM_NAME = Sha512Hash.ALGORITHM_NAME;
-    public static final Integer HASH_ITERATIONS = Integer.parseInt(System.getProperty(KILLBILL_TENANT_HASH_ITERATIONS_PROPERTY, "200000"));
 
     private KillbillCredentialsMatcher() {}
 
-    public static CredentialsMatcher getCredentialsMatcher() {
+    public static CredentialsMatcher getCredentialsMatcher(final SecurityConfig securityConfig) {
         // This needs to be in sync with DefaultTenantDao
         final HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(HASH_ALGORITHM_NAME);
         // base64 encoding, not hex
         credentialsMatcher.setStoredCredentialsHexEncoded(false);
-        credentialsMatcher.setHashIterations(HASH_ITERATIONS);
+        credentialsMatcher.setHashIterations(securityConfig.getShiroNbHashIterations());
 
         return credentialsMatcher;
     }
diff --git a/util/src/main/java/org/killbill/billing/util/security/shiro/realm/KillBillJdbcRealm.java b/util/src/main/java/org/killbill/billing/util/security/shiro/realm/KillBillJdbcRealm.java
index 9806abe..380258b 100644
--- a/util/src/main/java/org/killbill/billing/util/security/shiro/realm/KillBillJdbcRealm.java
+++ b/util/src/main/java/org/killbill/billing/util/security/shiro/realm/KillBillJdbcRealm.java
@@ -24,6 +24,7 @@ import javax.sql.DataSource;
 import org.apache.shiro.realm.jdbc.JdbcRealm;
 import org.apache.shiro.subject.PrincipalCollection;
 import org.killbill.billing.platform.glue.KillBillPlatformModuleBase;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.killbill.billing.util.security.shiro.KillbillCredentialsMatcher;
 
 public class KillBillJdbcRealm extends JdbcRealm {
@@ -33,11 +34,13 @@ public class KillBillJdbcRealm extends JdbcRealm {
     protected static final String KILLBILL_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ? and is_active";
 
     private final DataSource dataSource;
+    private final SecurityConfig securityConfig;
 
     @Inject
-    public KillBillJdbcRealm(@Named(KillBillPlatformModuleBase.SHIRO_DATA_SOURCE_ID_NAMED) final DataSource dataSource) {
+    public KillBillJdbcRealm(@Named(KillBillPlatformModuleBase.SHIRO_DATA_SOURCE_ID_NAMED) final DataSource dataSource, final SecurityConfig securityConfig) {
         super();
         this.dataSource = dataSource;
+        this.securityConfig = securityConfig;
 
         // Tweak JdbcRealm defaults
         setPermissionsLookupEnabled(true);
@@ -56,7 +59,7 @@ public class KillBillJdbcRealm extends JdbcRealm {
 
     private void configureSecurity() {
         setSaltStyle(SaltStyle.COLUMN);
-        setCredentialsMatcher(KillbillCredentialsMatcher.getCredentialsMatcher());
+        setCredentialsMatcher(KillbillCredentialsMatcher.getCredentialsMatcher(securityConfig));
     }
 
     private void configureDataSource() {
diff --git a/util/src/test/java/org/killbill/billing/util/security/shiro/realm/TestKillBillJdbcRealm.java b/util/src/test/java/org/killbill/billing/util/security/shiro/realm/TestKillBillJdbcRealm.java
index 540f375..931e546 100644
--- a/util/src/test/java/org/killbill/billing/util/security/shiro/realm/TestKillBillJdbcRealm.java
+++ b/util/src/test/java/org/killbill/billing/util/security/shiro/realm/TestKillBillJdbcRealm.java
@@ -50,7 +50,7 @@ public class TestKillBillJdbcRealm extends UtilTestSuiteWithEmbeddedDB {
     @BeforeMethod(groups = "slow")
     public void beforeMethod() throws Exception {
         super.beforeMethod();
-        final KillBillJdbcRealm realm = new KillBillJdbcRealm(helper.getDataSource());
+        final KillBillJdbcRealm realm = new KillBillJdbcRealm(helper.getDataSource(), securityConfig);
         securityManager = new DefaultSecurityManager(realm);
         SecurityUtils.setSecurityManager(securityManager);
     }
diff --git a/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java b/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
index df64546..6bdbbb3 100644
--- a/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
@@ -26,6 +26,7 @@ import org.killbill.billing.security.api.SecurityApi;
 import org.killbill.billing.util.audit.dao.AuditDao;
 import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.config.SecurityConfig;
 import org.killbill.billing.util.customfield.api.DefaultCustomFieldUserApi;
 import org.killbill.billing.util.customfield.dao.CustomFieldDao;
 import org.killbill.billing.util.dao.NonEntityDao;
@@ -84,6 +85,8 @@ public abstract class UtilTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
     protected TestApiListener eventsListener;
     @Inject
     protected SecurityApi securityApi;
+    @Inject
+    protected SecurityConfig securityConfig;
 
     @BeforeClass(groups = "slow")
     public void beforeClass() throws Exception {