diff options
Diffstat (limited to 'odl-aaa-moon/aaa-authn-store/src/main/java')
2 files changed, 199 insertions, 0 deletions
diff --git a/odl-aaa-moon/aaa-authn-store/src/main/java/org/opendaylight/aaa/store/Activator.java b/odl-aaa-moon/aaa-authn-store/src/main/java/org/opendaylight/aaa/store/Activator.java new file mode 100644 index 00000000..f3299723 --- /dev/null +++ b/odl-aaa-moon/aaa-authn-store/src/main/java/org/opendaylight/aaa/store/Activator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.store; + +import java.util.Dictionary; +import org.apache.felix.dm.DependencyActivatorBase; +import org.apache.felix.dm.DependencyManager; +import org.opendaylight.aaa.api.TokenStore; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.service.cm.ManagedService; + +/** + * An activator for the default datastore implementation of {@link TokenStore}. + * + * @author liemmn + */ +public class Activator extends DependencyActivatorBase { + + private static final String TOKEN_PID = "org.opendaylight.aaa.tokens"; + + @Override + public void init(BundleContext context, DependencyManager manager) throws Exception { + DefaultTokenStore ts = new DefaultTokenStore(); + manager.add(createComponent().setInterface(new String[] { TokenStore.class.getName() }, + null).setImplementation(ts)); + context.registerService(ManagedService.class.getName(), ts, + addPid(DefaultTokenStore.defaults)); + } + + @Override + public void destroy(BundleContext context, DependencyManager manager) throws Exception { + } + + private Dictionary<String, ?> addPid(Dictionary<String, String> dict) { + dict.put(Constants.SERVICE_PID, TOKEN_PID); + return dict; + } +} diff --git a/odl-aaa-moon/aaa-authn-store/src/main/java/org/opendaylight/aaa/store/DefaultTokenStore.java b/odl-aaa-moon/aaa-authn-store/src/main/java/org/opendaylight/aaa/store/DefaultTokenStore.java new file mode 100644 index 00000000..df65be32 --- /dev/null +++ b/odl-aaa-moon/aaa-authn-store/src/main/java/org/opendaylight/aaa/store/DefaultTokenStore.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.store; + +import java.io.File; +import java.lang.management.ManagementFactory; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.locks.ReentrantLock; +import javax.management.MBeanServer; +import net.sf.ehcache.Cache; +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.Element; +import net.sf.ehcache.config.CacheConfiguration; +import net.sf.ehcache.management.ManagementService; +import org.apache.felix.dm.Component; +import org.opendaylight.aaa.api.Authentication; +import org.opendaylight.aaa.api.TokenStore; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A default token store for STS. + * + * @author liemmn + * + */ +public class DefaultTokenStore implements TokenStore, ManagedService { + private static final Logger LOG = LoggerFactory.getLogger(DefaultTokenStore.class); + private static final String TOKEN_STORE_CONFIG_ERR = "Token store configuration error"; + + private static final String TOKEN_CACHE_MANAGER = "org.opendaylight.aaa"; + private static final String TOKEN_CACHE = "tokens"; + private static final String EHCACHE_XML = "etc/ehcache.xml"; + + static final String MAX_CACHED_MEMORY = "maxCachedTokensInMemory"; + static final String MAX_CACHED_DISK = "maxCachedTokensOnDisk"; + static final String SECS_TO_LIVE = "secondsToLive"; + static final String SECS_TO_IDLE = "secondsToIdle"; + + // Defaults (needed only for non-Karaf deployments) + static final Dictionary<String, String> defaults = new Hashtable<>(); + static { + defaults.put(MAX_CACHED_MEMORY, Long.toString(10000)); + defaults.put(MAX_CACHED_DISK, Long.toString(1000000)); + defaults.put(SECS_TO_IDLE, Long.toString(3600)); + defaults.put(SECS_TO_LIVE, Long.toString(3600)); + } + + // Token cache lock + private static final ReentrantLock cacheLock = new ReentrantLock(); + + // Token cache + private Cache tokens; + + // This should be a singleton + DefaultTokenStore() { + } + + // Called by DM when all required dependencies are satisfied. + void init(Component c) { + File ehcache = new File(EHCACHE_XML); + CacheManager cm; + if (ehcache.exists()) { + cm = CacheManager.create(ehcache.getAbsolutePath()); + tokens = cm.getCache(TOKEN_CACHE); + LOG.info("Initialized token store with custom cache config"); + } else { + cm = CacheManager.getInstance(); + tokens = new Cache( + new CacheConfiguration(TOKEN_CACHE, + Integer.parseInt(defaults.get(MAX_CACHED_MEMORY))).maxEntriesLocalDisk( + Integer.parseInt(defaults.get(MAX_CACHED_DISK))) + .timeToLiveSeconds( + Long.parseLong(defaults.get(SECS_TO_LIVE))) + .timeToIdleSeconds( + Long.parseLong(defaults.get(SECS_TO_IDLE)))); + cm.addCache(tokens); + LOG.info("Initialized token store with default cache config"); + } + cm.setName(TOKEN_CACHE_MANAGER); + + // JMX for cache management + MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); + ManagementService.registerMBeans(cm, mBeanServer, false, false, false, true); + } + + // Called on shutdown + void destroy() { + LOG.info("Shutting down token store..."); + CacheManager.getInstance().shutdown(); + } + + @Override + public Authentication get(String token) { + Element elem = tokens.get(token); + return (Authentication) ((elem != null) ? elem.getObjectValue() : null); + } + + @Override + public void put(String token, Authentication auth) { + tokens.put(new Element(token, auth)); + } + + @Override + public boolean delete(String token) { + return tokens.remove(token); + } + + @Override + public long tokenExpiration() { + return tokens.getCacheConfiguration().getTimeToLiveSeconds(); + } + + @Override + public void updated(@SuppressWarnings("rawtypes") Dictionary props) + throws ConfigurationException { + LOG.info("Updating token store configuration..."); + if (props == null) { + // Someone deleted the configuration, use defaults + props = defaults; + } + reconfig(props); + } + + // Refresh cache configuration... + private void reconfig(@SuppressWarnings("rawtypes") Dictionary props) + throws ConfigurationException { + cacheLock.lock(); + try { + long secsToIdle = Long.parseLong(props.get(SECS_TO_IDLE).toString()); + long secsToLive = Long.parseLong(props.get(SECS_TO_LIVE).toString()); + int maxMem = Integer.parseInt(props.get(MAX_CACHED_MEMORY).toString()); + int maxDisk = Integer.parseInt(props.get(MAX_CACHED_DISK).toString()); + CacheConfiguration config = tokens.getCacheConfiguration(); + config.setTimeToIdleSeconds(secsToIdle); + config.setTimeToLiveSeconds(secsToLive); + config.maxEntriesLocalHeap(maxMem); + config.maxEntriesLocalDisk(maxDisk); + } catch (Throwable t) { + throw new ConfigurationException(null, TOKEN_STORE_CONFIG_ERR, t); + } finally { + cacheLock.unlock(); + } + } +} |