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) };