Repository: karaf
Updated Branches:
  refs/heads/master 2fefe3fa9 -> 49afe847f


[KARAF-3006] Provide an EventAdmin based audit trail for JAAS

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/f6d42087
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/f6d42087
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/f6d42087

Branch: refs/heads/master
Commit: f6d4208733ded8299ca2eb0630552e9b1e943d9f
Parents: 2fefe3f
Author: Guillaume Nodet <gno...@gmail.com>
Authored: Tue May 27 17:52:01 2014 +0200
Committer: Guillaume Nodet <gno...@gmail.com>
Committed: Tue May 27 17:52:01 2014 +0200

----------------------------------------------------------------------
 jaas/modules/pom.xml                            |   1 +
 .../eventadmin/EventAdminLoginModule.java       | 131 +++++++++++++++++++
 .../karaf/jaas/modules/impl/KarafRealm.java     |  12 ++
 3 files changed, 144 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/f6d42087/jaas/modules/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/modules/pom.xml b/jaas/modules/pom.xml
index 2f70e1e..76205ac 100644
--- a/jaas/modules/pom.xml
+++ b/jaas/modules/pom.xml
@@ -127,6 +127,7 @@
                         <Import-Package>
                             javax.net,
                             org.apache.karaf.jaas.config,
+                            org.osgi.service.event;resolution:=optional,
                             *
                         </Import-Package>
                         <Private-Package>

http://git-wip-us.apache.org/repos/asf/karaf/blob/f6d42087/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/eventadmin/EventAdminLoginModule.java
----------------------------------------------------------------------
diff --git 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/eventadmin/EventAdminLoginModule.java
 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/eventadmin/EventAdminLoginModule.java
new file mode 100644
index 0000000..e831fa6
--- /dev/null
+++ 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/eventadmin/EventAdminLoginModule.java
@@ -0,0 +1,131 @@
+/*
+ *  Licensed 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.
+ *  under the License.
+ */
+package org.apache.karaf.jaas.modules.eventadmin;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+public class EventAdminLoginModule implements LoginModule {
+
+    public static final String TOPIC_EVENTS = "org/apache/karaf/jaas";
+    public static final String TOPIC_LOGIN = TOPIC_EVENTS + "/LOGIN";
+    public static final String TOPIC_SUCCESS = TOPIC_EVENTS + "/SUCCESS";
+    public static final String TOPIC_FAILURE = TOPIC_EVENTS + "/FAILURE";
+    public static final String TOPIC_LOGOUT = TOPIC_EVENTS + "/LOGOUT";
+
+    private Subject subject;
+    private CallbackHandler handler;
+    private Map<String, ?> options;
+    private String username;
+    private BundleContext bundleContext;
+
+    @Override
+    public void initialize(Subject subject, CallbackHandler handler, 
Map<String, ?> sharedState, Map<String, ?> options) {
+        this.subject = subject;
+        this.handler = handler;
+        this.options = options;
+        this.bundleContext = (BundleContext) 
options.get(BundleContext.class.getName());
+    }
+
+    @Override
+    public boolean login() throws LoginException {
+        NameCallback user = new NameCallback("User name:");
+        Callback[] callbacks = new Callback[]{user};
+        try {
+            handler.handle(callbacks);
+        } catch (Exception e) {
+            throw (LoginException) new LoginException("Unable to process 
callback: " + e.getMessage()).initCause(e);
+        }
+        if (callbacks.length != 1) {
+            throw new IllegalStateException("Number of callbacks changed by 
server!");
+        }
+        user = (NameCallback) callbacks[0];
+        username = user.getName();
+        sendEvent(TOPIC_LOGIN);
+        return false;
+    }
+
+    @Override
+    public boolean commit() throws LoginException {
+        if (username != null) {
+            sendEvent(TOPIC_SUCCESS);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean abort() throws LoginException {
+        if (username != null) { //work around initial "fake" login
+            sendEvent(TOPIC_FAILURE);
+            username = null;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean logout() throws LoginException {
+        if (username != null) {
+            sendEvent(TOPIC_LOGOUT);
+            username = null;
+        }
+        return false;
+    }
+
+    private void sendEvent(String topic) {
+        if (Boolean.parseBoolean((String) options.get("eventadmin.enabled"))) {
+            Dictionary<String, Object> props = new Hashtable<>();
+            props.put("type", topic.substring(topic.lastIndexOf("/") + 
1).toLowerCase());
+            props.put("timestamp", System.currentTimeMillis());
+            props.put("username", username);
+            props.put("subject", subject);
+
+            try {
+                Inner.send(bundleContext, topic, props);
+            } catch (Throwable t) {
+                // Ignore
+            }
+        }
+    }
+
+    static class Inner {
+
+        public static void send(BundleContext bundleContext, String topic, 
Dictionary<String, Object> props) {
+            ServiceReference<EventAdmin> ref = 
bundleContext.getServiceReference(EventAdmin.class);
+            if (ref != null) {
+                EventAdmin admin = bundleContext.getService(ref);
+                try {
+                    admin.sendEvent(new Event(topic, props));
+                } finally {
+                    bundleContext.ungetService(ref);
+                }
+            }
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f6d42087/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/impl/KarafRealm.java
----------------------------------------------------------------------
diff --git 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/impl/KarafRealm.java 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/impl/KarafRealm.java
index a04d5ac..33d9c44 100644
--- 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/impl/KarafRealm.java
+++ 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/impl/KarafRealm.java
@@ -33,6 +33,7 @@ public class KarafRealm implements JaasRealm, ManagedService {
 
     private static final String KARAF_ETC = System.getProperty("karaf.etc");
     private static final String REALM = "karaf";
+    private static final String EVENTADMIN_MODULE = 
"org.apache.karaf.jaas.modules.eventadmin.EventAdminLoginModule";
     private static final String PROPERTIES_MODULE = 
"org.apache.karaf.jaas.modules.properties.PropertiesLoginModule";
     private static final String PUBLIC_KEY_MODULE = 
"org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule";
 
@@ -42,6 +43,9 @@ public class KarafRealm implements JaasRealm, ManagedService {
     private static final String ENCRYPTION_SUFFIX = "encryption.suffix";
     private static final String ENCRYPTION_ALGORITHM = "encryption.algorithm";
     private static final String ENCRYPTION_ENCODING = "encryption.encoding";
+
+    private static final String EVENTADMIN_ENABLED = "eventadmin.enabled";
+
     private static final String MODULE = "org.apache.karaf.jaas.module";
 
     private final BundleContext bundleContext;
@@ -61,6 +65,7 @@ public class KarafRealm implements JaasRealm, ManagedService {
         props.put(ENCRYPTION_SUFFIX, "{CRYPT}");
         props.put(ENCRYPTION_ALGORITHM, "MD5");
         props.put(ENCRYPTION_ENCODING, "hexadecimal");
+        props.put(EVENTADMIN_ENABLED, "true");
     }
 
     @Override
@@ -102,7 +107,14 @@ public class KarafRealm implements JaasRealm, 
ManagedService {
         publicKeyOptions.put(ProxyLoginModule.PROPERTY_BUNDLE, 
Long.toString(bundleContext.getBundle().getBundleId()));
         publicKeyOptions.put("users", KARAF_ETC + File.separatorChar + 
"keys.properties");
 
+        Map<String, Object> eventadminOptions = new HashMap<>();
+        eventadminOptions.putAll(properties);
+        eventadminOptions.put(BundleContext.class.getName(), bundleContext);
+        eventadminOptions.put(ProxyLoginModule.PROPERTY_MODULE, 
EVENTADMIN_MODULE);
+        eventadminOptions.put(ProxyLoginModule.PROPERTY_BUNDLE, 
Long.toString(bundleContext.getBundle().getBundleId()));
+
         return new AppConfigurationEntry[] {
+                new AppConfigurationEntry(ProxyLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, eventadminOptions),
                 new AppConfigurationEntry(ProxyLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, propertiesOptions),
                 new AppConfigurationEntry(ProxyLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, publicKeyOptions)
         };

Reply via email to