Skip to content

Commit f3a225f

Browse files
committed
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.
1 parent 43c0c93 commit f3a225f

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfiguration.java

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@
4444
import org.crsh.vfs.spi.FSDriver;
4545
import org.springframework.beans.factory.ListableBeanFactory;
4646
import org.springframework.beans.factory.annotation.Autowired;
47+
import org.springframework.boot.actuate.properties.SecurityProperties;
48+
import org.springframework.boot.actuate.properties.SecurityProperties.Management;
4749
import org.springframework.boot.actuate.properties.ShellProperties;
4850
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties;
51+
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellProperties;
4952
import org.springframework.boot.actuate.properties.ShellProperties.JaasAuthenticationProperties;
5053
import org.springframework.boot.actuate.properties.ShellProperties.KeyAuthenticationProperties;
5154
import org.springframework.boot.actuate.properties.ShellProperties.SimpleAuthenticationProperties;
@@ -76,20 +79,32 @@
7679

7780
/**
7881
* {@link EnableAutoConfiguration Auto-configuration} for embedding an extensible shell
79-
* into a Spring Boot enabled application. By default a SSH daemon is started on port 2000
80-
* with a default username <code>user</code> and password (default password is logged
81-
* during application startup).
82+
* into a Spring Boot enabled application. By default a SSH daemon is started on port
83+
* 2000. If the CRaSH Telnet plugin is available on the classpath, Telnet deamon will be
84+
* launched on port 5000.
8285
*
8386
* <p>
84-
* This configuration will auto detect the existence of a Spring Security
85-
* {@link AuthenticationManager} and will delegate authentication requests for shell
86-
* access to this detected instance if <code>shell.auth: spring</code> is set in the
87-
* application properties.
87+
* The default shell authentication method uses a username and password combination. If no
88+
* configuration is provided the default username is 'user' and the password will be
89+
* printed to console during application startup. Those default values can be overridden
90+
* by using <code>shell.auth.simple.username</code> and
91+
* <code>shell.auth.simple.password</code>.
92+
*
93+
* <p>
94+
* If a Spring Security {@link AuthenticationManager} is detected, this configuration will
95+
* create a {@link CRaSHPlugin} to forward shell authentication requests to Spring
96+
* Security. This authentication method will get enabled if <code>shell.auth</code> is set
97+
* to <code>spring</code> or if no explicit <code>shell.auth</code> is provided and a
98+
* {@link AuthenticationManager} is available. In the latter case shell access will be
99+
* restricted to users having roles that match those configured in {@link Management}.
100+
* Required roles can be overridden by <code>shell.auth.spring.roles</code>.
88101
*
89102
* <p>
90103
* To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in
91104
* the application context. Those beans will get auto detected during startup and
92-
* registered with the underlying shell infrastructure.
105+
* registered with the underlying shell infrastructure. To configure plugins and the CRaSH
106+
* infrastructure add beans of type {@link CrshShellProperties} to the application
107+
* context.
93108
*
94109
* <p>
95110
* Additional shell commands can be implemented using the guide and documentation at <a
@@ -99,6 +114,7 @@
99114
* <code>shell.command_path_patterns</code> in your application configuration.
100115
*
101116
* @author Christian Dupuis
117+
* @see ShellProperties
102118
*/
103119
@Configuration
104120
@ConditionalOnClass({ PluginLifeCycle.class })
@@ -145,15 +161,36 @@ public PluginLifeCycle shellBootstrap() {
145161
return bootstrapBean;
146162
}
147163

164+
/**
165+
* Class to configure CRaSH to authenticate against Spring Security.
166+
*/
148167
@Configuration
149168
@ConditionalOnBean({ AuthenticationManager.class })
169+
@AutoConfigureAfter(CrshAutoConfiguration.class)
150170
public static class AuthenticationManagerAdapterAutoConfiguration {
151171

172+
@Autowired(required = false)
173+
private SecurityProperties securityProperties;
174+
152175
@Bean
153176
public CRaSHPlugin<?> shellAuthenticationManager() {
154177
return new AuthenticationManagerAdapter();
155178
}
156179

180+
@Bean
181+
@ConditionalOnExpression("'${shell.auth:default_spring}' == 'default_spring'")
182+
@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
183+
public CrshShellAuthenticationProperties springAuthenticationProperties() {
184+
// In case no shell.auth property is provided fall back to Spring Security
185+
// based authentication and get role to access shell from SecurityProperties.
186+
SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
187+
if (this.securityProperties != null) {
188+
authenticationProperties.setRoles(new String[] { this.securityProperties
189+
.getManagement().getRole() });
190+
}
191+
return authenticationProperties;
192+
}
193+
157194
}
158195

159196
/**
@@ -238,7 +275,7 @@ private static class AuthenticationManagerAdapter extends
238275
@Autowired(required = false)
239276
private AccessDecisionManager accessDecisionManager;
240277

241-
private String[] roles = new String[] { "ROLE_ADMIN" };
278+
private String[] roles = new String[] { "ADMIN" };
242279

243280
@Override
244281
public boolean authenticate(String username, String password) throws Exception {

spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfigurationTests.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ public void testDefaultAuthenticationProvider() {
190190
this.context = new AnnotationConfigWebApplicationContext();
191191
this.context.setEnvironment(env);
192192
this.context.setServletContext(new MockServletContext());
193-
this.context.register(SecurityConfiguration.class);
194193
this.context.register(CrshAutoConfiguration.class);
195194
this.context.refresh();
196195

@@ -295,6 +294,35 @@ public void testSpringAuthenticationProvider() throws Exception {
295294
SecurityConfiguration.PASSWORD));
296295
}
297296

297+
@Test
298+
public void testSpringAuthenticationProviderAsDefaultConfiguration() throws Exception {
299+
this.context = new AnnotationConfigWebApplicationContext();
300+
this.context.setServletContext(new MockServletContext());
301+
this.context.register(ManagementServerPropertiesAutoConfiguration.class);
302+
this.context.register(SecurityAutoConfiguration.class);
303+
this.context.register(SecurityConfiguration.class);
304+
this.context.register(CrshAutoConfiguration.class);
305+
this.context.refresh();
306+
307+
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
308+
309+
AuthenticationPlugin<String> authenticationPlugin = null;
310+
String authentication = lifeCycle.getConfig().getProperty("crash.auth");
311+
assertNotNull(authentication);
312+
for (AuthenticationPlugin plugin : lifeCycle.getContext().getPlugins(
313+
AuthenticationPlugin.class)) {
314+
if (authentication.equals(plugin.getName())) {
315+
authenticationPlugin = plugin;
316+
break;
317+
}
318+
}
319+
assertTrue(authenticationPlugin.authenticate(SecurityConfiguration.USERNAME,
320+
SecurityConfiguration.PASSWORD));
321+
322+
assertFalse(authenticationPlugin.authenticate(UUID.randomUUID().toString(),
323+
SecurityConfiguration.PASSWORD));
324+
}
325+
298326
@Configuration
299327
public static class SecurityConfiguration {
300328

0 commit comments

Comments
 (0)