66import com .google .common .cache .CacheBuilder ;
77import com .google .common .cache .CacheLoader ;
88import com .google .common .cache .LoadingCache ;
9- import com .google .common .util .concurrent .ListenableFuture ;
10- import com .google .common .util .concurrent .ListenableFutureTask ;
119import io .containx .marathon .plugin .auth .type .AuthKey ;
1210import io .containx .marathon .plugin .auth .type .Configuration ;
1311import io .containx .marathon .plugin .auth .type .UserIdentity ;
1917import mesosphere .marathon .plugin .http .HttpResponse ;
2018import mesosphere .marathon .plugin .plugin .PluginConfiguration ;
2119import play .api .libs .json .JsObject ;
20+ import play .api .libs .json .JsValue ;
2221import scala .Option ;
2322import scala .concurrent .ExecutionContext ;
2423import scala .concurrent .Future ;
2524import org .slf4j .Logger ;
2625import org .slf4j .LoggerFactory ;
2726
28- import javax .naming .NamingException ;
29- import java .io .IOException ;
27+ import java .util .Map ;
3028import java .util .Set ;
31- import java .util .concurrent .Callable ;
3229import java .util .concurrent .Executors ;
33- import java .util .concurrent .ThreadFactory ;
30+ import java .util .concurrent .ScheduledExecutorService ;
3431import java .util .concurrent .TimeUnit ;
32+ import javax .naming .NamingException ;
3533
3634public class LDAPAuthenticator implements Authenticator , PluginConfiguration {
3735
3836 private static final Logger LOGGER = LoggerFactory .getLogger (LDAPAuthenticator .class );
37+ private AccessRulesUpdaterTask accessRulesUpdaterTask ;
38+ private final ScheduledExecutorService scheduler = Executors .newScheduledThreadPool (1 );
39+ private final long DEFAULT_INTERVAL_IN_SECONDS = 60 ;
40+ private long refreshInterval = DEFAULT_INTERVAL_IN_SECONDS ;
3941
4042 private final ExecutionContext EC = ExecutionContexts
4143 .fromExecutorService (
4244 Executors .newSingleThreadExecutor (r -> new Thread (r , "Ldap-ExecutorThread" ))
4345 );
4446
45- private final LoadingCache <AuthKey , UserIdentity > USERS = CacheBuilder .newBuilder ()
46- .maximumSize (2000 )
47- .expireAfterWrite (60 , TimeUnit .MINUTES )
48- .refreshAfterWrite (5 , TimeUnit .MINUTES )
49- .build (
50- CacheLoader .asyncReloading (
51- new CacheLoader <AuthKey , UserIdentity >() {
52- @ Override
53- public UserIdentity load (AuthKey key ) throws Exception {
54- return (UserIdentity ) doAuth (key .getUsername (), key .getPassword ());
55- }
56- }
57- , Executors .newSingleThreadExecutor (
58- r -> new Thread (r , "Ldap-CacheLoaderExecutorThread" )
59- )
60- )
61- );
47+ private LoadingCache <AuthKey , UserIdentity > USERS ;
6248
6349 private Configuration config ;
6450
6551 @ Override
6652 public void initialize (scala .collection .immutable .Map <String , Object > map , JsObject jsObject ) {
53+ Map <String , JsValue > conf = scala .collection .JavaConverters .mapAsJavaMap (jsObject .value ());
54+ String intervalKey = "refresh-interval-seconds" ;
55+ if (conf .containsKey (intervalKey )){
56+ refreshInterval = Long .parseLong (conf .get (intervalKey ).toString ());
57+ if (refreshInterval <= 0 ) {
58+ refreshInterval = DEFAULT_INTERVAL_IN_SECONDS ;
59+ }
60+ }
61+ USERS = CacheBuilder .newBuilder ()
62+ .maximumSize (2000 )
63+ .expireAfterWrite (60 , TimeUnit .MINUTES )
64+ .refreshAfterWrite (refreshInterval , TimeUnit .SECONDS )
65+ .build (
66+ CacheLoader .asyncReloading (
67+ new CacheLoader <AuthKey , UserIdentity >() {
68+ @ Override
69+ public UserIdentity load (AuthKey key ) throws Exception {
70+ return (UserIdentity ) doAuth (key .getUsername (), key .getPassword ());
71+ }
72+ }
73+ , Executors .newSingleThreadExecutor (
74+ r -> new Thread (r , "Ldap-CacheLoaderExecutorThread" )
75+ )
76+ )
77+ );
6778 try {
6879 config = new ObjectMapper ().readValue (jsObject .toString (), Configuration .class );
69- } catch (IOException e ) {
80+ if (config .getLdap ().getRulesUpdaterBindUser () != null ) {
81+ accessRulesUpdaterTask = new AccessRulesUpdaterTask (config );
82+ scheduler .scheduleAtFixedRate (accessRulesUpdaterTask , 0 , refreshInterval , TimeUnit .SECONDS );
83+ }
84+ } catch (Exception e ) {
7085 LOGGER .error ("Error reading configuration JSON: {}" , e .getMessage (), e );
7186 }
7287 }
@@ -78,6 +93,9 @@ public Future<Option<Identity>> authenticate(HttpRequest request) {
7893
7994 private Identity doAuth (HttpRequest request ) {
8095 try {
96+ if (accessRulesUpdaterTask != null ) {
97+ config .setAuthorization (accessRulesUpdaterTask .getAccessRules ());
98+ }
8199 AuthKey ak = HTTPHelper .authKeyFromHeaders (request );
82100 if (ak != null ) {
83101
@@ -110,6 +128,10 @@ private Identity doAuth(String username, String password) throws NamingException
110128 int count = 0 ;
111129 int maxTries = 5 ;
112130
131+ if (accessRulesUpdaterTask != null ) {
132+ config .setAuthorization (accessRulesUpdaterTask .getAccessRules ());
133+ }
134+
113135 while (true ) {
114136 try {
115137 Set <String > memberships = LDAPHelper .validate (username , password , config .getLdap ());
@@ -120,7 +142,6 @@ private Identity doAuth(String username, String password) throws NamingException
120142 }
121143 } catch (Exception ex ) {
122144 LOGGER .error ("LDAP error Exception: {}" , ex );
123-
124145 if (++count == maxTries ) throw ex ;
125146 }
126147 }
0 commit comments