Skip to content
This repository has been archived by the owner on Apr 8, 2019. It is now read-only.

Commit

Permalink
Delegate 'authorization' to to extensions and remove @RolesAllowed fr…
Browse files Browse the repository at this point in the history
…om RestController so unauthenticated access is allowed
  • Loading branch information
nscavell committed Apr 1, 2013
1 parent 5e2fe79 commit 7bdcb1e
Show file tree
Hide file tree
Showing 15 changed files with 222 additions and 131 deletions.
Expand Up @@ -37,4 +37,13 @@ public interface RuntimeContext
* @return the runtime component
*/
<T> T getRuntimeComponent(Class<T> componentClass);

/**
* Returns a boolean indicating whether the user is included in the specified logical "role". If user is not
* authenticated this returns false.
*
* @param role the name of the role
* @return true if the user belongs to a given role or false if user is not authenticated
*/
boolean isUserInRole(String role);
}
@@ -0,0 +1,38 @@
package org.gatein.management.api.exceptions;

import org.gatein.management.api.ManagedUser;

/**
* @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
*/
public class NotAuthorizedException extends OperationException
{
private final ManagedUser user;

public NotAuthorizedException(ManagedUser user, String operationName)
{
super(operationName, createMessage(user, operationName));
this.user = user;
}

public NotAuthorizedException(ManagedUser user, String operationName, Throwable cause)
{
super(operationName, createMessage(user, operationName), cause);
this.user = user;
}

public ManagedUser getUser()
{
return user;
}

private static String createMessage(ManagedUser user, String operationName)
{
if (user == null)
{
return "Authentication required for operation " + operationName;
}

return user.getUserName() + " is not authorized to execute operation " + operationName;
}
}
Expand Up @@ -43,10 +43,19 @@ public interface OperationContext
{
/**
*
* @return the user if one is associated with the request
* @return the user if one is associated with the request. Returns null if user it not authenticated.
*/
ManagedUser getUser();

/**
* Returns a boolean indicating whether the user is included in the specified logical "role". If user is not
* authenticated this returns false.
*
* @param role the name of the role
* @return true if the user belongs to a given role or false if user is not authenticated
*/
boolean isUserInRole(String role);

/**
*
* @return Path of the current operation.
Expand Down
Expand Up @@ -52,6 +52,12 @@ public ManagedUser getUser()
return delegate.getUser();
}

@Override
public boolean isUserInRole(String role)
{
return delegate.isUserInRole(role);
}

@Override
public PathAddress getAddress()
{
Expand Down
Expand Up @@ -28,9 +28,7 @@
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;

import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
Expand All @@ -41,6 +39,8 @@ public class GateInCommand extends CRaSHCommand
{
private static final Logger log = LoggerFactory.getLogger(GateInCommand.class);

private Object conversationState;

protected GateInCommand() throws IntrospectionException
{
}
Expand All @@ -60,63 +60,22 @@ protected <T> T getComponent(String containerName, Class<T> componentClass) thro
}
}

protected Session login(String userName, String password, String containerName) throws ScriptException
protected void start(String userName, String containerName)
{
Object container = getContainer(containerName);

// TODO: Find better way to "authenticate"
try
{
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
Method getComponentInstanceOfTypeMethod = container.getClass().getMethod("getComponentInstanceOfType", Class.class);

// Set current identity (similar to SetCurrentIdentityFilter behavior)
Class<?> authenticatorClass = tccl.loadClass("org.exoplatform.services.security.Authenticator");
Object authenticator = getComponentInstanceOfTypeMethod.invoke(container, authenticatorClass);
Method createIdentityMethod = authenticatorClass.getMethod("createIdentity", String.class);
Object identity = createIdentityMethod.invoke(authenticator, userName);
Class<?> identityRegistryClass = tccl.loadClass("org.exoplatform.services.security.IdentityRegistry");
Class<?> identityClass = tccl.loadClass("org.exoplatform.services.security.Identity");
Object identityRegistry = getComponentInstanceOfTypeMethod.invoke(container, identityRegistryClass);
Method registerIdentityMethod = identityRegistryClass.getMethod("register", identityClass);
registerIdentityMethod.invoke(identityRegistry, identity);

// Log into the JCR to determine authorization
Class<?> repositoryServiceClass = tccl.loadClass("org.exoplatform.services.jcr.RepositoryService");
Object repositoryService = getComponentInstanceOfTypeMethod.invoke(container, repositoryServiceClass);
if (repositoryService != null)
{
Method getCurrentRepositoryMethod = repositoryService.getClass().getMethod("getCurrentRepository");
Repository repository = (Repository) getCurrentRepositoryMethod.invoke(repositoryService);
SimpleCredentials credentials = new SimpleCredentials(userName, password.toCharArray());
Session session = repository.login(credentials, "portal-system");
if (session == null)
{
throw new Exception("JCR Session was null.");
}

// This verifies the user has access to the JCR.
session.getRootNode();

return session;
}
else
{
throw new Exception("Repository service was null.");
}
}
catch (Exception e)
if (conversationState == null)
{
throw new ScriptException("Could not authenticate for user '" + userName + "'", e);
conversationState = getConversationState(userName, containerName);
}
}

protected void start(String containerName)
{
try
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();

// Set current conversation state
Class<?> conversationStateClass = cl.loadClass("org.exoplatform.services.security.ConversationState");
Method setCurrent = conversationStateClass.getMethod("setCurrent", conversationStateClass);
setCurrent.invoke(null, conversationState);

// Set the current container
Class<?> eXoContainerContextClass = cl.loadClass("org.exoplatform.container.ExoContainerContext");
Class<?> eXoContainerClass = cl.loadClass("org.exoplatform.container.ExoContainer");
Expand Down Expand Up @@ -192,4 +151,38 @@ private Object getContainer(String containerName) throws ScriptException

return container;
}

private Object getConversationState(String userName, String containerName) throws ScriptException
{
Object container = getContainer(containerName);

try
{
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
Method getComponentInstanceOfTypeMethod = container.getClass().getMethod("getComponentInstanceOfType", Class.class);

// Set current identity (similar to SetCurrentIdentityFilter behavior)
Class<?> identityRegistryClass = tccl.loadClass("org.exoplatform.services.security.IdentityRegistry");
Method getIdentityMethod = identityRegistryClass.getMethod("getIdentity", String.class);
Class<?> identityClass = tccl.loadClass("org.exoplatform.services.security.Identity");
Object identityRegistry = getComponentInstanceOfTypeMethod.invoke(container, identityRegistryClass);
Object identity = getIdentityMethod.invoke(identityRegistry, userName);
if (identity == null)
{
Class<?> authenticatorClass = tccl.loadClass("org.exoplatform.services.security.Authenticator");
Object authenticator = getComponentInstanceOfTypeMethod.invoke(container, authenticatorClass);
Method createIdentityMethod = authenticatorClass.getMethod("createIdentity", String.class);
identity = createIdentityMethod.invoke(authenticator, userName);
Method registerIdentityMethod = identityRegistryClass.getMethod("register", identityClass);
registerIdentityMethod.invoke(identityRegistry, identity);
}
Class<?> conversationStateClass = tccl.loadClass("org.exoplatform.services.security.ConversationState");
Constructor<?> conversationStateConstructor = conversationStateClass.getConstructor(identityClass);
return conversationStateConstructor.newInstance(identity);
}
catch (Exception e)
{
throw new ScriptException("Could not authenticate for user '" + userName + "'", e);
}
}
}
Expand Up @@ -26,6 +26,7 @@
import org.crsh.cmdline.IntrospectionException;
import org.crsh.cmdline.ParameterDescriptor;
import org.crsh.cmdline.spi.Completer;
import org.crsh.command.InvocationContext;
import org.crsh.command.ScriptException;
import org.gatein.management.api.PathAddress;
import org.gatein.management.api.controller.ManagedRequest;
Expand Down
Expand Up @@ -33,6 +33,8 @@
import org.gatein.common.logging.LoggerFactory;
import org.gatein.management.api.controller.ManagementController;
import org.gatein.management.cli.crash.commands.ManagementCommand;
import org.gatein.management.cli.crash.plugins.CustomWebPluginLifecycle;
import org.gatein.management.cli.crash.plugins.JaasAuthenticationPlugin;

import javax.jcr.Session;
import java.io.ByteArrayOutputStream;
Expand All @@ -54,6 +56,7 @@ public abstract class SCPCommand extends AbstractCommand implements Runnable

private String path;
private String containerName;
private String jaasDomain;

private SCPManagementCommand scpManagementCommand;
private Thread thread;
Expand All @@ -69,6 +72,7 @@ public void start(Environment environment) throws IOException
try
{
scpManagementCommand = new SCPManagementCommand();
jaasDomain = CustomWebPluginLifecycle.getCrashProperties().getProperty("crash.jaas.domain", "gatein-domain");
}
catch (IntrospectionException e)
{
Expand Down Expand Up @@ -108,16 +112,20 @@ public void run()

private void execute() throws Exception
{
// Log in
String userName = session.getAttribute(SSHLifeCycle.USERNAME);
String password = session.getAttribute(SSHLifeCycle.PASSWORD);

// Log in
log.debug("Attempting to authenticate user " + userName);
JaasAuthenticationPlugin jaas = new JaasAuthenticationPlugin();
boolean authenticated = jaas.login(userName, password, jaasDomain);

Session jcrSession = scpManagementCommand.login(userName, password, containerName);
if (jcrSession == null) throw new Exception("JCR session was null.");
if (!authenticated)
{
throw new Exception("Could not authenticate for user " + userName);
}

scpManagementCommand.start(containerName);
scpManagementCommand.start(userName, containerName);
try
{
// Parse attributes
Expand Down Expand Up @@ -153,10 +161,6 @@ private void execute() throws Exception
finally
{
scpManagementCommand.end();
if (jcrSession.isLive())
{
jcrSession.logout();
}
}
}

Expand Down Expand Up @@ -246,15 +250,9 @@ protected SCPManagementCommand() throws IntrospectionException
}

@Override
protected Session login(String userName, String password, String containerName) throws ScriptException
{
return super.login(userName, password, containerName);
}

@Override
protected void start(String containerName)
protected void start(String userName, String containerName)
{
super.start(containerName);
super.start(userName, containerName);
}

@Override
Expand Down
@@ -0,0 +1,62 @@
package org.gatein.management.cli.crash.plugins;

import org.crsh.plugin.WebPluginLifeCycle;
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;

import javax.servlet.ServletContextEvent;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
* Used to bootstrap crash and also provide access to crash.properties data.
*
* @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
*/
public class CustomWebPluginLifecycle extends WebPluginLifeCycle
{
private static final Properties crashProperties = new Properties();
private static final Logger log = LoggerFactory.getLogger(CustomWebPluginLifecycle.class);

public static Properties getCrashProperties()
{
return crashProperties;
}

@Override
public void contextInitialized(ServletContextEvent sce)
{
super.contextInitialized(sce);
String path = "/WEB-INF/crash/crash.properties";
InputStream in = sce.getServletContext().getResourceAsStream(path);
try
{
crashProperties.load(in);
}
catch (IOException e)
{
log.error("Exception reading file " + path, e);
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e)
{
}
}
}
}

@Override
public void contextDestroyed(ServletContextEvent sce)
{
super.contextDestroyed(sce);
crashProperties.clear();
}
}
Expand Up @@ -35,6 +35,7 @@
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -75,6 +76,11 @@ protected Iterable<PropertyDescriptor<?>> createConfigurationCapabilities()
public boolean authenticate(final String username, final String password) throws Exception
{
String domain = getContext().getProperty(JAAS_DOMAIN);
return login(username, password, domain);
}

public boolean login(final String username, final String password, final String domain) throws LoginException
{
if (domain != null)
{
log.debug("Will use the JAAS domain '" + domain + "' for authenticating user " + username +" into CRaSH.");
Expand Down

0 comments on commit 7bdcb1e

Please sign in to comment.