Commit f3a225f3 authored by Christian Dupuis's avatar Christian Dupuis

Polish and rework default authentication method if a Spring Security...

Polish and rework default authentication method if a Spring Security AuthenticationManager is available

In case a Spring Security AuthenticationManager is found in the app context the auto configuration will change default shell authentication method to auth against Spring Security. In addition shell access will get protected by the specific role configured in SecurityProperties.Management.

Certainly this can be overridden by providing shell.auth and shell.auth.spring.roles.
parent 43c0c932
...@@ -44,8 +44,11 @@ import org.crsh.vfs.spi.AbstractFSDriver; ...@@ -44,8 +44,11 @@ import org.crsh.vfs.spi.AbstractFSDriver;
import org.crsh.vfs.spi.FSDriver; import org.crsh.vfs.spi.FSDriver;
import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.properties.SecurityProperties;
import org.springframework.boot.actuate.properties.SecurityProperties.Management;
import org.springframework.boot.actuate.properties.ShellProperties; import org.springframework.boot.actuate.properties.ShellProperties;
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties; import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellProperties;
import org.springframework.boot.actuate.properties.ShellProperties.JaasAuthenticationProperties; import org.springframework.boot.actuate.properties.ShellProperties.JaasAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.KeyAuthenticationProperties; import org.springframework.boot.actuate.properties.ShellProperties.KeyAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.SimpleAuthenticationProperties; import org.springframework.boot.actuate.properties.ShellProperties.SimpleAuthenticationProperties;
...@@ -76,20 +79,32 @@ import org.springframework.util.StringUtils; ...@@ -76,20 +79,32 @@ import org.springframework.util.StringUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for embedding an extensible shell * {@link EnableAutoConfiguration Auto-configuration} for embedding an extensible shell
* into a Spring Boot enabled application. By default a SSH daemon is started on port 2000 * into a Spring Boot enabled application. By default a SSH daemon is started on port
* with a default username <code>user</code> and password (default password is logged * 2000. If the CRaSH Telnet plugin is available on the classpath, Telnet deamon will be
* during application startup). * launched on port 5000.
* *
* <p> * <p>
* This configuration will auto detect the existence of a Spring Security * The default shell authentication method uses a username and password combination. If no
* {@link AuthenticationManager} and will delegate authentication requests for shell * configuration is provided the default username is 'user' and the password will be
* access to this detected instance if <code>shell.auth: spring</code> is set in the * printed to console during application startup. Those default values can be overridden
* application properties. * by using <code>shell.auth.simple.username</code> and
* <code>shell.auth.simple.password</code>.
*
* <p>
* If a Spring Security {@link AuthenticationManager} is detected, this configuration will
* create a {@link CRaSHPlugin} to forward shell authentication requests to Spring
* Security. This authentication method will get enabled if <code>shell.auth</code> is set
* to <code>spring</code> or if no explicit <code>shell.auth</code> is provided and a
* {@link AuthenticationManager} is available. In the latter case shell access will be
* restricted to users having roles that match those configured in {@link Management}.
* Required roles can be overridden by <code>shell.auth.spring.roles</code>.
* *
* <p> * <p>
* To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in * To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in
* the application context. Those beans will get auto detected during startup and * the application context. Those beans will get auto detected during startup and
* registered with the underlying shell infrastructure. * registered with the underlying shell infrastructure. To configure plugins and the CRaSH
* infrastructure add beans of type {@link CrshShellProperties} to the application
* context.
* *
* <p> * <p>
* Additional shell commands can be implemented using the guide and documentation at <a * Additional shell commands can be implemented using the guide and documentation at <a
...@@ -99,6 +114,7 @@ import org.springframework.util.StringUtils; ...@@ -99,6 +114,7 @@ import org.springframework.util.StringUtils;
* <code>shell.command_path_patterns</code> in your application configuration. * <code>shell.command_path_patterns</code> in your application configuration.
* *
* @author Christian Dupuis * @author Christian Dupuis
* @see ShellProperties
*/ */
@Configuration @Configuration
@ConditionalOnClass({ PluginLifeCycle.class }) @ConditionalOnClass({ PluginLifeCycle.class })
...@@ -145,15 +161,36 @@ public class CrshAutoConfiguration { ...@@ -145,15 +161,36 @@ public class CrshAutoConfiguration {
return bootstrapBean; return bootstrapBean;
} }
/**
* Class to configure CRaSH to authenticate against Spring Security.
*/
@Configuration @Configuration
@ConditionalOnBean({ AuthenticationManager.class }) @ConditionalOnBean({ AuthenticationManager.class })
@AutoConfigureAfter(CrshAutoConfiguration.class)
public static class AuthenticationManagerAdapterAutoConfiguration { public static class AuthenticationManagerAdapterAutoConfiguration {
@Autowired(required = false)
private SecurityProperties securityProperties;
@Bean @Bean
public CRaSHPlugin<?> shellAuthenticationManager() { public CRaSHPlugin<?> shellAuthenticationManager() {
return new AuthenticationManagerAdapter(); return new AuthenticationManagerAdapter();
} }
@Bean
@ConditionalOnExpression("'${shell.auth:default_spring}' == 'default_spring'")
@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
public CrshShellAuthenticationProperties springAuthenticationProperties() {
// In case no shell.auth property is provided fall back to Spring Security
// based authentication and get role to access shell from SecurityProperties.
SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
if (this.securityProperties != null) {
authenticationProperties.setRoles(new String[] { this.securityProperties
.getManagement().getRole() });
}
return authenticationProperties;
}
} }
/** /**
...@@ -238,7 +275,7 @@ public class CrshAutoConfiguration { ...@@ -238,7 +275,7 @@ public class CrshAutoConfiguration {
@Autowired(required = false) @Autowired(required = false)
private AccessDecisionManager accessDecisionManager; private AccessDecisionManager accessDecisionManager;
private String[] roles = new String[] { "ROLE_ADMIN" }; private String[] roles = new String[] { "ADMIN" };
@Override @Override
public boolean authenticate(String username, String password) throws Exception { public boolean authenticate(String username, String password) throws Exception {
......
...@@ -190,7 +190,6 @@ public class CrshAutoConfigurationTests { ...@@ -190,7 +190,6 @@ public class CrshAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setEnvironment(env); this.context.setEnvironment(env);
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
this.context.register(SecurityConfiguration.class);
this.context.register(CrshAutoConfiguration.class); this.context.register(CrshAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
...@@ -295,6 +294,35 @@ public class CrshAutoConfigurationTests { ...@@ -295,6 +294,35 @@ public class CrshAutoConfigurationTests {
SecurityConfiguration.PASSWORD)); SecurityConfiguration.PASSWORD));
} }
@Test
public void testSpringAuthenticationProviderAsDefaultConfiguration() throws Exception {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(ManagementServerPropertiesAutoConfiguration.class);
this.context.register(SecurityAutoConfiguration.class);
this.context.register(SecurityConfiguration.class);
this.context.register(CrshAutoConfiguration.class);
this.context.refresh();
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
AuthenticationPlugin<String> authenticationPlugin = null;
String authentication = lifeCycle.getConfig().getProperty("crash.auth");
assertNotNull(authentication);
for (AuthenticationPlugin plugin : lifeCycle.getContext().getPlugins(
AuthenticationPlugin.class)) {
if (authentication.equals(plugin.getName())) {
authenticationPlugin = plugin;
break;
}
}
assertTrue(authenticationPlugin.authenticate(SecurityConfiguration.USERNAME,
SecurityConfiguration.PASSWORD));
assertFalse(authenticationPlugin.authenticate(UUID.randomUUID().toString(),
SecurityConfiguration.PASSWORD));
}
@Configuration @Configuration
public static class SecurityConfiguration { public static class SecurityConfiguration {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment