You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2011/06/09 17:22:43 UTC
svn commit: r1133926 - in /activemq/activemq-apollo/trunk:
apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/
apollo-util/src/main/scala/org/apache/activemq/apollo/util/
Author: chirino
Date: Thu Jun 9 15:22:43 2011
New Revision: 1133926
URL: http://svn.apache.org/viewvc?rev=1133926&view=rev
Log:
Fixes https://issues.apache.org/jira/browse/APLO-42 : File based JAAS login modules should cache file contents until changed.
Added:
activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/FileCache.scala
Modified:
activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/CertificateLoginModule.scala
activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileGroupLoginModule.scala
activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileUserLoginModule.scala
activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SocketAddressLoginModule.scala
Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/CertificateLoginModule.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/CertificateLoginModule.scala?rev=1133926&r1=1133925&r2=1133926&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/CertificateLoginModule.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/CertificateLoginModule.scala Thu Jun 9 15:22:43 2011
@@ -27,11 +27,13 @@ import java.security.cert.X509Certificat
import java.{util => ju}
import java.io.{FileInputStream, File, IOException}
import org.yaml.snakeyaml.Yaml
-import org.apache.activemq.apollo.util.{FileSupport, Log}
import java.lang.String
import org.apache.activemq.jaas.{UserPrincipal, CertificateCallback}
-import java.util.LinkedList
import javax.security.auth.spi.LoginModule
+import java.util.{Properties, LinkedList}
+import org.apache.activemq.apollo.util.FileSupport._
+import org.apache.activemq.apollo.util.{FileCache, FileSupport, Log}
+import org.apache.activemq.apollo.util.Log._
/**
* <p>
@@ -43,6 +45,21 @@ object CertificateLoginModule {
val LOGIN_CONFIG = "java.security.auth.login.config"
val FILE_OPTION = "dn_file"
val DEFAULT_LOG = Log(getClass)
+
+ def load_dns(file:File):Option[java.util.Map[String, AnyRef]] = {
+ try {
+ import FileSupport._
+ using( new FileInputStream(file) ) { in=>
+ Some((new Yaml().load(in)).asInstanceOf[java.util.Map[String, AnyRef]])
+ }
+ } catch {
+ case e: Throwable =>
+ DEFAULT_LOG.warn(e, "Unable to load the distinguished name file: " + file)
+ None
+ }
+ }
+
+ val file_cache = new FileCache[java.util.Map[String, AnyRef]](load_dns)
}
/**
@@ -112,16 +129,10 @@ class CertificateLoginModule extends Log
}
case Some(file)=>
- val users = try {
- import FileSupport._
- using( new FileInputStream(file) ) { in=>
- (new Yaml().load(in)).asInstanceOf[java.util.Map[String, AnyRef]]
- }
- } catch {
- case e: Throwable =>
- warn(e, "Unable to load the distinguished name file: " + file)
- e.printStackTrace
- throw new LoginException("Invalid login module configuration")
+
+ val users = file_cache.get(file) match {
+ case None => throw new LoginException("Invalid login module configuration")
+ case Some(x) => x
}
for (cert <- certificates) {
Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileGroupLoginModule.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileGroupLoginModule.scala?rev=1133926&r1=1133925&r2=1133926&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileGroupLoginModule.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileGroupLoginModule.scala Thu Jun 9 15:22:43 2011
@@ -34,7 +34,6 @@ package org.apache.activemq.apollo.broke
* limitations under the License.
*/
import java.io.File
-import java.io.FileInputStream
import java.security.Principal
import javax.security.auth.Subject
import javax.security.auth.callback.CallbackHandler
@@ -43,10 +42,9 @@ import javax.security.auth.spi.LoginModu
import org.apache.activemq.jaas.GroupPrincipal
import org.apache.activemq.jaas.UserPrincipal
import java.{util => ju}
-import org.apache.activemq.apollo.util.{FileSupport, Log}
-import FileSupport._
import java.util.regex.Pattern
-import java.util.{LinkedList, Properties}
+import java.util.LinkedList
+import org.apache.activemq.apollo.util.Log
object FileGroupLoginModule {
val LOGIN_CONFIG = "java.security.auth.login.config"
@@ -104,16 +102,9 @@ class FileGroupLoginModule extends Login
def commit: Boolean = {
- val groups = try {
- using( new FileInputStream(file) ) { in=>
- val groups = new Properties()
- groups.load(in)
- groups
- }
- } catch {
- case e: Throwable =>
- warn(e, "Unable to load group properties file " + file)
- return false;
+ val groups = FileUserLoginModule.file_cache.get(file) match {
+ case None => return false
+ case Some(x) => x
}
import collection.JavaConversions._
Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileUserLoginModule.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileUserLoginModule.scala?rev=1133926&r1=1133925&r2=1133926&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileUserLoginModule.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/FileUserLoginModule.scala Thu Jun 9 15:22:43 2011
@@ -34,13 +34,30 @@ import javax.security.auth.spi.LoginModu
import org.apache.activemq.jaas.UserPrincipal
import java.{util => ju}
-import org.apache.activemq.apollo.util.{FileSupport, Log}
+import org.apache.activemq.apollo.util.{FileCache, Log, FileSupport}
import FileSupport._
object FileUserLoginModule {
val LOGIN_CONFIG = "java.security.auth.login.config"
val FILE_OPTION = "file"
val DEFAULT_LOG = Log(getClass)
+
+ def load_properties(file:File):Option[Properties] = {
+ try {
+ val rc = new Properties()
+ using( new FileInputStream(file) ) { in=>
+ rc.load(in)
+ }
+ EncryptionSupport.decrypt(rc)
+ Some(rc)
+ } catch {
+ case e: Throwable =>
+ DEFAULT_LOG.warn(e, "Unable to load properties file: " + file)
+ None
+ }
+ }
+
+ val file_cache = new FileCache[Properties](load_properties)
}
/**
@@ -80,16 +97,9 @@ class FileUserLoginModule extends LoginM
}
def login: Boolean = {
- val users = new Properties()
- try {
- using( new FileInputStream(file) ) { in=>
- users.load(in)
- }
- EncryptionSupport.decrypt(users)
- } catch {
- case e: Throwable =>
- warn(e, "Unable to load user properties file: " + file)
- return false
+ val users = file_cache.get(file) match {
+ case None => return false
+ case Some(x) => x
}
val callbacks = new Array[Callback](2)
Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SocketAddressLoginModule.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SocketAddressLoginModule.scala?rev=1133926&r1=1133925&r2=1133926&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SocketAddressLoginModule.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SocketAddressLoginModule.scala Thu Jun 9 15:22:43 2011
@@ -22,11 +22,11 @@ import javax.security.auth.callback.Call
import javax.security.auth.callback.UnsupportedCallbackException
import javax.security.auth.login.LoginException
import java.{util => ju}
-import java.io.{File, IOException}
-import org.apache.activemq.apollo.util.{FileSupport, Log}
import java.lang.String
import javax.security.auth.spi.LoginModule
-import java.net.{InetSocketAddress, SocketAddress, InetAddress}
+import java.net.{InetSocketAddress, SocketAddress}
+import java.io.{File, IOException}
+import org.apache.activemq.apollo.util.{FileCache, FileSupport, Log}
/**
* <p>
@@ -39,6 +39,26 @@ object SocketAddressLoginModule {
val WHITE_LIST_OPTION = "white_list_file"
val BLACK_LIST_OPTION = "black_list_file"
val DEFAULT_LOG = Log(getClass)
+
+ def load_line_set(file:File):Option[Set[String]] = {
+ try {
+ import FileSupport._
+ val rc: Set[String] = file.read_text().split("\n").map(_.trim()).toSet
+ Some(rc.flatMap { line =>
+ if(line.isEmpty || line.startsWith("#")) {
+ None
+ } else {
+ Some(line)
+ }
+ })
+ } catch {
+ case e: Throwable =>
+ DEFAULT_LOG.warn(e, "Unable to load file: " + file)
+ None
+ }
+ }
+
+ val file_cache = new FileCache[Set[String]](load_line_set)
}
/**
@@ -112,15 +132,17 @@ class SocketAddressLoginModule extends L
}
def matches(file:File, address:SocketAddress):Boolean = {
-
val needle = address match {
case address:InetSocketAddress =>
address.getAddress.getHostAddress
case _ => return false
}
- import FileSupport._
- file.read_text().split("\n").find( _.trim() == needle ).isDefined
+ file_cache.get(file) match {
+ case None => false
+ case Some(haystack) =>
+ haystack.contains(needle)
+ }
}
def commit: Boolean = {
Added: activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/FileCache.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/FileCache.scala?rev=1133926&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/FileCache.scala (added)
+++ activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/FileCache.scala Thu Jun 9 15:22:43 2011
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.apollo.util
+
+import java.io.File
+import java.lang.Long
+import org.fusesource.hawtdispatch._
+import scala.Some
+import java.util.concurrent.{TimeUnit, ConcurrentHashMap}
+
+
+/**
+ * <p>
+ * Class used to maintain a cache of loaded files which gets
+ * evicted periodically via async time stamp checks.
+ * </p>
+ *
+ * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
+ */
+class FileCache[T](mapper: (File)=>Option[T], evict_after:Long=1000*60*5) {
+
+ class Entry(val file:File, val modified:Long, @volatile var last_accessed:Long, val value:Option[T])
+
+ private val cache = new ConcurrentHashMap[File, Entry]()
+ private var eviction_ver = 0
+
+ def get(file:File):Option[T] = {
+ var rc = cache.get(file)
+ val now: Long = System.currentTimeMillis()
+ if( rc == null ) {
+ rc = if ( !file.exists() ) {
+ new Entry(file, 0, now, None)
+ } else {
+ new Entry(file, file.lastModified(), now, mapper(file))
+ }
+ this.synchronized {
+ cache.put(file, rc)
+ if( cache.size() == 1) {
+ eviction_ver += 1;
+ val ver = eviction_ver
+ globalQueue.after(1, TimeUnit.SECONDS)(eviction_check(ver))
+ }
+ }
+ }
+ rc.last_accessed = now
+ rc.value
+ }
+
+ def eviction_check(ver:Int):Unit = {
+ if (ver == eviction_ver) {
+ import collection.JavaConversions._
+ val evict_point = System.currentTimeMillis() - evict_after
+ val evictions = cache.values().flatMap { entry =>
+ if(
+ entry.value == None ||
+ !entry.file.exists() ||
+ entry.file.lastModified() != entry.modified ||
+ entry.last_accessed < evict_point
+ ) {
+ Some(entry.file)
+ } else {
+ None
+ }
+ }
+ evictions.foreach(f => cache.remove(f))
+ this.synchronized {
+ if( cache.size() == 0) {
+ eviction_ver += 1;
+ } else {
+ globalQueue.after(1, TimeUnit.SECONDS)(eviction_check(ver))
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file