Repository: karaf Updated Branches: refs/heads/KARAF-5427 [created] 103f33105
[KARAF-5427] Add RBAC support for reflection invocation and redirections in the console Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/103f3310 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/103f3310 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/103f3310 Branch: refs/heads/KARAF-5427 Commit: 103f33105a58c899706a0687bb334678e2fa1ee7 Parents: 066d28a Author: Guillaume Nodet <[email protected]> Authored: Mon Oct 16 15:59:45 2017 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Mon Oct 16 15:59:45 2017 +0200 ---------------------------------------------------------------------- pom.xml | 4 +- .../shell/impl/console/SessionFactoryImpl.java | 22 +++++++++- .../console/osgi/secured/SecuredCommand.java | 2 +- .../osgi/secured/SecuredSessionFactoryImpl.java | 42 ++++++++++++++------ 4 files changed, 54 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/103f3310/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 2e7778b..d0cced3 100644 --- a/pom.xml +++ b/pom.xml @@ -192,8 +192,8 @@ <felix.fileinstall.version>3.6.2</felix.fileinstall.version> <felix.framework.version>5.6.8</felix.framework.version> <felix.framework.security.version>2.6.0</felix.framework.security.version> - <felix.gogo.runtime.version>1.0.8</felix.gogo.runtime.version> - <felix.gogo.jline.version>1.0.8</felix.gogo.jline.version> + <felix.gogo.runtime.version>1.0.9-SNAPSHOT</felix.gogo.runtime.version> + <felix.gogo.jline.version>1.0.9-SNAPSHOT</felix.gogo.jline.version> <felix.httplite.version>0.1.6</felix.httplite.version> <felix.inventory.version>1.0.4</felix.inventory.version> <felix.plugin.version>3.3.0</felix.plugin.version> http://git-wip-us.apache.org/repos/asf/karaf/blob/103f3310/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java ---------------------------------------------------------------------- diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java index d351753..13e27ac 100644 --- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java +++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java @@ -20,6 +20,7 @@ package org.apache.karaf.shell.impl.console; import java.io.InputStream; import java.io.PrintStream; +import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -29,6 +30,7 @@ import org.apache.felix.gogo.jline.Builtin; import org.apache.felix.gogo.jline.Posix; import org.apache.felix.gogo.jline.Procedural; import org.apache.felix.gogo.runtime.CommandProcessorImpl; +import org.apache.felix.gogo.runtime.CommandSessionImpl; import org.apache.felix.gogo.runtime.Reflective; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Function; @@ -54,7 +56,17 @@ public class SessionFactoryImpl extends RegistryImpl implements SessionFactory, public SessionFactoryImpl(ThreadIO threadIO) { super(null); this.threadIO = threadIO; - commandProcessor = new CommandProcessorImpl(threadIO); + commandProcessor = new CommandProcessorImpl(threadIO) { + @Override + public Object invoke(CommandSessionImpl session, Object target, String name, List<Object> args) throws Exception { + return SessionFactoryImpl.this.invoke(session, target, name, args); + } + + @Override + public Path redirect(CommandSessionImpl session, Path path, int mode) { + return SessionFactoryImpl.this.redirect(session, path, mode); + } + }; register(new ExitCommand()); new HelpCommand(this); register(new ShellCommand("addCommand", "Add a command", commandProcessor, "addCommand")); @@ -77,6 +89,14 @@ public class SessionFactoryImpl extends RegistryImpl implements SessionFactory, } } + protected Object invoke(CommandSessionImpl session, Object target, String name, List<Object> args) throws Exception { + return Reflective.invoke(session, target, name, args); + } + + protected Path redirect(CommandSessionImpl session, Path path, int mode) { + return session.currentDir().resolve(path); + } + public CommandProcessorImpl getCommandProcessor() { return commandProcessor; } http://git-wip-us.apache.org/repos/asf/karaf/blob/103f3310/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java ---------------------------------------------------------------------- diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java index e6e8ef7..2df6e09 100644 --- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java +++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java @@ -64,7 +64,7 @@ public class SecuredCommand implements Command, Function { @Override public Object execute(Session session, List<Object> arguments) throws Exception { - factory.checkSecurity(this, session, arguments); + factory.checkSecurity(getScope(), getName(), arguments); return command.execute(session, arguments); } http://git-wip-us.apache.org/repos/asf/karaf/blob/103f3310/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java ---------------------------------------------------------------------- diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java index cf12f18..7fe015c 100644 --- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java +++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java @@ -18,10 +18,12 @@ */ package org.apache.karaf.shell.impl.console.osgi.secured; +import java.nio.file.Path; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Principal; import java.util.ArrayList; +import java.util.Arrays; import java.util.Dictionary; import java.util.HashMap; import java.util.List; @@ -30,12 +32,12 @@ import java.util.Map; import javax.security.auth.Subject; import org.apache.felix.gogo.runtime.CommandNotFoundException; +import org.apache.felix.gogo.runtime.CommandSessionImpl; import org.apache.felix.service.command.Function; import org.apache.felix.service.threadio.ThreadIO; import org.apache.karaf.jaas.boot.principal.RolePrincipal; import org.apache.karaf.service.guard.tools.ACLConfigurationParser; import org.apache.karaf.shell.api.console.Command; -import org.apache.karaf.shell.api.console.Session; import org.apache.karaf.shell.impl.console.SessionFactoryImpl; import org.apache.karaf.util.tracker.SingleServiceTracker; import org.osgi.framework.BundleContext; @@ -52,8 +54,11 @@ import org.slf4j.LoggerFactory; public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements ConfigurationListener { private static final String PROXY_COMMAND_ACL_PID_PREFIX = "org.apache.karaf.command.acl."; - private static final String CONFIGURATION_FILTER = - "(" + Constants.SERVICE_PID + "=" + PROXY_COMMAND_ACL_PID_PREFIX + "*)"; + private static final String CONFIGURATION_FILTER = "(" + Constants.SERVICE_PID + "=" + PROXY_COMMAND_ACL_PID_PREFIX + "*)"; + + private static final String SHELL_SCOPE = "shell"; + private static final String SHELL_INVOKE = ".invoke"; + private static final String SHELL_REDIRECT = ".redirect"; private static final Logger LOGGER = LoggerFactory.getLogger(SecuredSessionFactoryImpl.class); @@ -77,6 +82,18 @@ public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements Con } @Override + protected Object invoke(CommandSessionImpl session, Object target, String name, List<Object> args) throws Exception { + checkSecurity(SHELL_SCOPE, SHELL_INVOKE, Arrays.asList(target, name, args)); + return super.invoke(session, target, name, args); + } + + @Override + protected Path redirect(CommandSessionImpl session, Path path, int mode) { + checkSecurity(SHELL_SCOPE, SHELL_REDIRECT, Arrays.asList(path, mode)); + return super.redirect(session, path, mode); + } + + @Override protected Function wrap(Command command) { return new SecuredCommand(this, command); } @@ -84,17 +101,18 @@ public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements Con @Override protected boolean isVisible(Object service) { if (service instanceof Command) { - return isVisible((Command) service); + Command cmd = (Command) service; + return isVisible(cmd.getScope(), cmd.getName()); } else { return super.isVisible(service); } } - protected boolean isVisible(Command command) { - Dictionary<String, Object> config = getScopeConfig(command.getScope()); + protected boolean isVisible(String scope, String name) { + Dictionary<String, Object> config = getScopeConfig(scope); if (config != null) { List<String> roles = new ArrayList<>(); - ACLConfigurationParser.getRolesForInvocation(command.getName(), null, null, config, roles); + ACLConfigurationParser.getRolesForInvocation(name, null, null, config, roles); if (roles.isEmpty()) { return true; } else { @@ -109,14 +127,14 @@ public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements Con return true; } - void checkSecurity(SecuredCommand command, Session session, List<Object> arguments) { - Dictionary<String, Object> config = getScopeConfig(command.getScope()); + void checkSecurity(String scope, String name, List<Object> arguments) { + Dictionary<String, Object> config = getScopeConfig(scope); if (config != null) { - if (!isVisible(command)) { - throw new CommandNotFoundException(command.getScope() + ":" + command.getName()); + if (!isVisible(scope, name)) { + throw new CommandNotFoundException(scope + ":" + name); } List<String> roles = new ArrayList<>(); - ACLConfigurationParser.Specificity s = ACLConfigurationParser.getRolesForInvocation(command.getName(), new Object[] { arguments.toString() }, null, config, roles); + ACLConfigurationParser.Specificity s = ACLConfigurationParser.getRolesForInvocation(name, new Object[] { arguments.toString() }, null, config, roles); if (s == ACLConfigurationParser.Specificity.NO_MATCH) { return; }
