killbill-memoizeit

Details

diff --git a/profiles/killbill/src/main/java/org/apache/shiro/authc/pam/ModularRealmAuthenticatorWith540.java b/profiles/killbill/src/main/java/org/apache/shiro/authc/pam/ModularRealmAuthenticatorWith540.java
index 14c5eda..3595863 100644
--- a/profiles/killbill/src/main/java/org/apache/shiro/authc/pam/ModularRealmAuthenticatorWith540.java
+++ b/profiles/killbill/src/main/java/org/apache/shiro/authc/pam/ModularRealmAuthenticatorWith540.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2015 Groupon, Inc
- * Copyright 2015 The Billing Project, LLC
+ * Copyright 2015-2018 Groupon, Inc
+ * Copyright 2015-2018 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
@@ -18,6 +18,7 @@
 package org.apache.shiro.authc.pam;
 
 import java.util.Collection;
+import java.util.LinkedList;
 
 import org.apache.shiro.authc.AuthenticationInfo;
 import org.apache.shiro.authc.AuthenticationToken;
@@ -26,13 +27,19 @@ import org.killbill.billing.server.security.FirstSuccessfulStrategyWith540;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-// See https://issues.apache.org/jira/browse/SHIRO-540
+/**
+ * Fix for https://issues.apache.org/jira/browse/SHIRO-540
+ * Support for additional realms non injected
+ */
 public class ModularRealmAuthenticatorWith540 extends ModularRealmAuthenticator {
 
     private static final Logger log = LoggerFactory.getLogger(ModularRealmAuthenticator.class);
 
-    public ModularRealmAuthenticatorWith540(final ModularRealmAuthenticator delegate) {
-        setRealms(delegate.getRealms());
+    public ModularRealmAuthenticatorWith540(final Collection<Realm> realmsFromShiroIni, final ModularRealmAuthenticator delegate) {
+        // Note: order matters (the first successful match will win)
+        final Collection<Realm> realms = new LinkedList<Realm>(realmsFromShiroIni);
+        realms.addAll(delegate.getRealms());
+        setRealms(realms);
         setAuthenticationStrategy(delegate.getAuthenticationStrategy());
     }
 
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
index eaf9e55..d7ce566 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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
@@ -18,6 +18,9 @@
 
 package org.killbill.billing.server.modules;
 
+import java.util.Collection;
+import java.util.LinkedList;
+
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -25,8 +28,10 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
 import org.apache.shiro.authc.pam.ModularRealmAuthenticatorWith540;
+import org.apache.shiro.authz.ModularRealmAuthorizer;
 import org.apache.shiro.cache.CacheManager;
 import org.apache.shiro.guice.web.ShiroWebModuleWith435;
+import org.apache.shiro.realm.Realm;
 import org.apache.shiro.session.mgt.SessionManager;
 import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
 import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
@@ -38,9 +43,9 @@ import org.killbill.billing.server.security.KillBillWebSessionManager;
 import org.killbill.billing.server.security.KillbillJdbcTenantRealm;
 import org.killbill.billing.util.config.definition.RbacConfig;
 import org.killbill.billing.util.glue.EhcacheShiroManagerProvider;
-import org.killbill.billing.util.glue.IniRealmProvider;
 import org.killbill.billing.util.glue.JDBCSessionDaoProvider;
 import org.killbill.billing.util.glue.KillBillShiroModule;
+import org.killbill.billing.util.glue.RealmsFromShiroIniProvider;
 import org.killbill.billing.util.security.shiro.dao.JDBCSessionDao;
 import org.killbill.billing.util.security.shiro.realm.KillBillJdbcRealm;
 import org.killbill.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
@@ -82,8 +87,6 @@ public class KillBillShiroWebModule extends ShiroWebModuleWith435 {
         final RbacConfig config = new ConfigurationObjectFactory(configSource).build(RbacConfig.class);
         bind(RbacConfig.class).toInstance(config);
 
-        // Note: order matters (the first successful match will win, see below)
-        bindRealm().toProvider(IniRealmProvider.class).asEagerSingleton();
         bindRealm().to(KillBillJdbcRealm.class).asEagerSingleton();
         if (KillBillShiroModule.isLDAPEnabled()) {
             bindRealm().to(KillBillJndiLdapRealm.class).asEagerSingleton();
@@ -133,7 +136,7 @@ public class KillBillShiroWebModule extends ShiroWebModuleWith435 {
         }
     }
 
-    private static final class DefaultWebSecurityManagerTypeListener implements TypeListener {
+    private final class DefaultWebSecurityManagerTypeListener implements TypeListener {
 
         @Override
         public <I> void hear(final TypeLiteral<I> typeLiteral, final TypeEncounter<I> typeEncounter) {
@@ -141,10 +144,21 @@ public class KillBillShiroWebModule extends ShiroWebModuleWith435 {
                 @Override
                 public void afterInjection(final Object o) {
                     final DefaultWebSecurityManager webSecurityManager = (DefaultWebSecurityManager) o;
+
+                    // Other realms have been injected by Guice (bindRealm().toInstance(...) makes Guice throw a ClassCastException?!)
+                    final Collection<Realm> realmsFromShiroIni = RealmsFromShiroIniProvider.get(configSource);
+
+                    if (webSecurityManager.getAuthorizer() instanceof ModularRealmAuthorizer) {
+                        final ModularRealmAuthorizer modularRealmAuthorizer = (ModularRealmAuthorizer) webSecurityManager.getAuthorizer();
+                        final Collection<Realm> realms = new LinkedList<Realm>(realmsFromShiroIni);
+                        realms.addAll(modularRealmAuthorizer.getRealms());
+                        modularRealmAuthorizer.setRealms(realms);
+                    }
+
                     if (webSecurityManager.getAuthenticator() instanceof ModularRealmAuthenticator) {
                         final ModularRealmAuthenticator authenticator = (ModularRealmAuthenticator) webSecurityManager.getAuthenticator();
                         authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategyWith540());
-                        webSecurityManager.setAuthenticator(new ModularRealmAuthenticatorWith540(authenticator));
+                        webSecurityManager.setAuthenticator(new ModularRealmAuthenticatorWith540(realmsFromShiroIni, authenticator));
                     }
                 }
             });
diff --git a/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java b/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
index c103789..154bc1d 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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,10 +21,13 @@ package org.killbill.billing.util.glue;
 import org.apache.shiro.cache.CacheManager;
 import org.apache.shiro.guice.ShiroModule;
 import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.text.IniRealm;
 import org.apache.shiro.session.mgt.DefaultSessionManager;
 import org.apache.shiro.session.mgt.SessionManager;
 import org.killbill.billing.platform.api.KillbillConfigSource;
 import org.killbill.billing.util.config.definition.RbacConfig;
+import org.killbill.billing.util.config.definition.SecurityConfig;
 import org.killbill.billing.util.security.shiro.dao.JDBCSessionDao;
 import org.killbill.billing.util.security.shiro.realm.KillBillJdbcRealm;
 import org.killbill.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
@@ -32,6 +35,7 @@ import org.killbill.billing.util.security.shiro.realm.KillBillOktaRealm;
 import org.skife.config.ConfigSource;
 import org.skife.config.ConfigurationObjectFactory;
 
+import com.google.inject.Provider;
 import com.google.inject.binder.AnnotatedBindingBuilder;
 
 // For Kill Bill library only.
@@ -42,7 +46,6 @@ public class KillBillShiroModule extends ShiroModule {
     public static final String KILLBILL_OKTA_PROPERTY = "killbill.server.okta";
     public static final String KILLBILL_RBAC_PROPERTY = "killbill.server.rbac";
 
-
     public static boolean isLDAPEnabled() {
         return Boolean.parseBoolean(System.getProperty(KILLBILL_LDAP_PROPERTY, "false"));
     }
@@ -70,11 +73,25 @@ public class KillBillShiroModule extends ShiroModule {
         }).build(RbacConfig.class);
         bind(RbacConfig.class).toInstance(config);
 
-        bindRealm().toProvider(IniRealmProvider.class).asEagerSingleton();
+        final ConfigSource skifeConfigSource = new ConfigSource() {
+            @Override
+            public String getString(final String propertyName) {
+                return configSource.getString(propertyName);
+            }
+        };
+
+        bind(RbacConfig.class).toInstance(config);
+
+        final Provider<IniRealm> iniRealmProvider = RealmsFromShiroIniProvider.getIniRealmProvider(skifeConfigSource);
+        // Hack for Kill Bill library to work around weird Guice ClassCastException when using
+        // bindRealm().toInstance(...) -- this means we don't support custom realms when embedding Kill Bill
+        bindRealm().toProvider(iniRealmProvider).asEagerSingleton();
 
         configureJDBCRealm();
 
         configureLDAPRealm();
+
+        configureOktaRealm();
     }
 
     protected void configureJDBCRealm() {