Repository: karaf Updated Branches: refs/heads/karaf-2.x 8a35113ea -> 4b8cc1022
http://git-wip-us.apache.org/repos/asf/karaf/blob/4b8cc102/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java ---------------------------------------------------------------------- diff --git a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java new file mode 100644 index 0000000..351a89f --- /dev/null +++ b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java @@ -0,0 +1,142 @@ +/* + * 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.karaf.shell.security.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.Subject; + +import org.apache.felix.gogo.api.CommandSessionListener; +import org.apache.felix.service.command.CommandProcessor; +import org.apache.felix.service.command.Converter; +import org.apache.felix.service.threadio.ThreadIO; +import org.apache.karaf.jaas.boot.principal.RolePrincipal; +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; + +public class SecuredCommandProcessorImplTest { + @Test + public void testCommandProcessor() throws Exception { + ThreadIO tio = EasyMock.createMock(ThreadIO.class); + EasyMock.replay(tio); + + @SuppressWarnings("unchecked") + ServiceReference<ThreadIO> tioRef = EasyMock.createMock(ServiceReference.class); + EasyMock.replay(tioRef); + + final BundleContext bc = EasyMock.createMock(BundleContext.class); + EasyMock.expect(bc.getServiceReference(ThreadIO.class)).andReturn(tioRef).anyTimes(); + EasyMock.expect(bc.getService(tioRef)).andReturn(tio).anyTimes(); + EasyMock.expect(bc.createFilter(EasyMock.isA(String.class))).andAnswer(new IAnswer<Filter>() { + @Override + public Filter answer() throws Throwable { + return FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0]); + } + }).anyTimes(); + EasyMock.expect(bc.getServiceReferences((String) EasyMock.anyObject(), (String) EasyMock.anyObject())).andReturn(null).anyTimes(); + + // Capture the listeners + final Map<String, ServiceListener> listeners = new HashMap<String, ServiceListener>(); + + // Here are the expected calls + final String commandFilter = "(&(osgi.command.scope=*)(osgi.command.function=*)" + + "(|(org.apache.karaf.service.guard.roles=aaabbbccc)(!(org.apache.karaf.service.guard.roles=*))))"; + expectServiceTracker(bc, commandFilter, listeners); + expectServiceTracker(bc, "(objectClass=" + Converter.class.getName() + ")", listeners); + expectServiceTracker(bc, "(objectClass=" + CommandSessionListener.class.getName() + ")", listeners); + EasyMock.replay(bc); + + Subject subject = new Subject(); + subject.getPrincipals().add(new RolePrincipal("aaabbbccc")); + + Subject.doAs(subject, new PrivilegedAction<Object>() { + @Override + public Object run() { + MySecuredCommandProcessorImpl scp = new MySecuredCommandProcessorImpl(bc) {}; + + assertEquals(3, scp.getCommands().size()); + assertTrue(scp.getCommands().contains("osgi:addcommand")); + assertTrue(scp.getCommands().contains("osgi:removecommand")); + assertTrue(scp.getCommands().contains("osgi:eval")); + assertEquals(1, scp.getConstants().size()); + assertEquals(bc, scp.getConstants().get(".context")); + + // Now let's make a command appear... + ServiceListener commandListener = listeners.get(commandFilter); + + ServiceReference<?> cdRef = EasyMock.createMock(ServiceReference.class); + EasyMock.expect(cdRef.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("foo"); + EasyMock.expect(cdRef.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn("bar"); + EasyMock.replay(cdRef); + + ServiceEvent event = new ServiceEvent(ServiceEvent.REGISTERED, cdRef); + commandListener.serviceChanged(event); + assertEquals(4, scp.getCommands().size()); + assertTrue(scp.getCommands().contains("foo:bar")); + + ServiceReference<?> cd2Ref = EasyMock.createMock(ServiceReference.class); + EasyMock.expect(cd2Ref.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("xxx"); + EasyMock.expect(cd2Ref.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn( + new String[] {"aaa", "bbb"}); + EasyMock.replay(cd2Ref); + + ServiceEvent event2 = new ServiceEvent(ServiceEvent.REGISTERED, cd2Ref); + commandListener.serviceChanged(event2); + assertEquals(6, scp.getCommands().size()); + assertTrue(scp.getCommands().contains("xxx:aaa")); + assertTrue(scp.getCommands().contains("xxx:bbb")); + + return null; + } + }); + } + + void expectServiceTracker(final BundleContext bc, final String expectedFilter, final Map<String, ServiceListener> listeners) throws InvalidSyntaxException { + bc.addServiceListener(EasyMock.isA(ServiceListener.class), EasyMock.eq(expectedFilter)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + listeners.put(expectedFilter, (ServiceListener) EasyMock.getCurrentArguments()[0]); + return null; + } + }).once(); + } + + // Subclass to provide access to some protected members + static class MySecuredCommandProcessorImpl extends SecuredCommandProcessorImpl { + public MySecuredCommandProcessorImpl(BundleContext bc) { + super(bc); + } + + Map<String, Object> getConstants() { + return constants; + } + }; +} http://git-wip-us.apache.org/repos/asf/karaf/blob/4b8cc102/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java ---------------------------------------------------------------------- diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java index 50eb5d1..0005892 100644 --- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java +++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java @@ -19,7 +19,6 @@ package org.apache.karaf.shell.ssh; import java.io.IOException; -import java.security.Principal; import java.security.PublicKey; import javax.security.auth.Subject; @@ -28,7 +27,6 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginContext; import org.apache.karaf.jaas.modules.publickey.PublickeyCallback; @@ -45,8 +43,7 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA private final Logger LOGGER = LoggerFactory.getLogger(KarafJaasAuthenticator.class); private String realm; - private String role; - + public String getRealm() { return realm; } @@ -55,13 +52,7 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA this.realm = realm; } - public String getRole() { - return role; - } - - public void setRole(String role) { - this.role = role; - } + public boolean authenticate(final String username, final String password, final ServerSession session) { try { @@ -80,26 +71,7 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA } }); loginContext.login(); - if (role != null && role.length() > 0) { - String clazz = "org.apache.karaf.jaas.boot.principal.RolePrincipal"; - String name = role; - int idx = role.indexOf(':'); - if (idx > 0) { - clazz = role.substring(0, idx); - name = role.substring(idx + 1); - } - boolean found = false; - for (Principal p : subject.getPrincipals()) { - if (p.getClass().getName().equals(clazz) - && p.getName().equals(name)) { - found = true; - break; - } - } - if (!found) { - throw new FailedLoginException("User does not have the required role " + role); - } - } + session.setAttribute(SUBJECT_ATTRIBUTE_KEY, subject); return true; } catch (Exception e) { @@ -125,26 +97,7 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA } }); loginContext.login(); - if (role != null && role.length() > 0) { - String clazz = "org.apache.karaf.jaas.boot.principal.RolePrincipal"; - String name = role; - int idx = role.indexOf(':'); - if (idx > 0) { - clazz = role.substring(0, idx); - name = role.substring(idx + 1); - } - boolean found = false; - for (Principal p : subject.getPrincipals()) { - if (p.getClass().getName().equals(clazz) - && p.getName().equals(name)) { - found = true; - break; - } - } - if (!found) { - throw new FailedLoginException("User does not have the required role " + role); - } - } + session.setAttribute(SUBJECT_ATTRIBUTE_KEY, subject); return true; } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/karaf/blob/4b8cc102/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java ---------------------------------------------------------------------- diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java index b4d3ad8..37fb37c 100644 --- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java +++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java @@ -42,6 +42,7 @@ import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; import org.apache.sshd.server.SessionAware; import org.apache.sshd.server.session.ServerSession; +import org.osgi.framework.BundleContext; import org.osgi.service.blueprint.container.ReifiedType; /** @@ -57,6 +58,7 @@ public class ShellFactoryImpl implements Factory<Command> { private CommandProcessor commandProcessor; private ThreadIO threadIO; + private BundleContext bundleContext; public void setCommandProcessor(CommandProcessor commandProcessor) { this.commandProcessor = commandProcessor; @@ -65,6 +67,10 @@ public class ShellFactoryImpl implements Factory<Command> { public void setThreadIO(ThreadIO threadIO) { this.threadIO = threadIO; } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } public Command create() { return new ShellImpl(); @@ -122,7 +128,8 @@ public class ShellFactoryImpl implements Factory<Command> { public void run() { destroy(); } - }); + }, + bundleContext); final CommandSession session = console.getSession(); session.put("APPLICATION", System.getProperty("karaf.name", "root")); for (Map.Entry<String,String> e : env.getEnv().entrySet()) { http://git-wip-us.apache.org/repos/asf/karaf/blob/4b8cc102/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml ---------------------------------------------------------------------- diff --git a/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml b/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml index 6ad80bd..54c3660 100644 --- a/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml +++ b/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml @@ -31,7 +31,6 @@ <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"> <ext:default-properties> <ext:property name="startRemoteShell" value="true" /> - <ext:property name="karaf.admin.role" value="admin" /> </ext:default-properties> </ext:property-placeholder> @@ -41,7 +40,6 @@ <cm:property name="sshHost" value="0.0.0.0"/> <cm:property name="sshIdleTimeout" value="1800000"/> <cm:property name="sshRealm" value="karaf"/> - <cm:property name="sshRole" value="$[karaf.admin.role]"/> <cm:property name="hostKey" value="$[karaf.etc]/host.key"/> <cm:property name="authorizedKeys" value="$[karaf.etc]/authorized_keys"/> <cm:property name="authMethods" value="keyboard-interactive,password,publickey"/> @@ -95,6 +93,7 @@ <bean class="org.apache.karaf.shell.ssh.ShellFactoryImpl"> <property name="commandProcessor" ref="commandProcessor"/> <property name="threadIO" ref="threadIO"/> + <property name="bundleContext" ref="blueprintBundleContext"/> </bean> </property> <property name="commandFactory"> @@ -137,7 +136,6 @@ </bean> <bean id="authenticator" class="org.apache.karaf.shell.ssh.KarafJaasAuthenticator"> <property name="realm" value="${sshRealm}"/> - <property name="role" value="${sshRole}"/> </bean> <bean id="sshServerFactory" class="org.apache.karaf.shell.ssh.SshServerFactory" init-method="start" http://git-wip-us.apache.org/repos/asf/karaf/blob/4b8cc102/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java ---------------------------------------------------------------------- diff --git a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java index 93c8655..0937d31 100644 --- a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java +++ b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java @@ -191,7 +191,8 @@ public class GogoPlugin extends AbstractWebConsolePlugin { pipedOut, new WebTerminal(TERM_WIDTH, TERM_HEIGHT), null, - null); + null, + bundleContext); CommandSession session = console.getSession(); session.put("APPLICATION", System.getProperty("karaf.name", "root")); session.put("USER", "karaf");
