diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfiguration.java
index 9cb691523b..db9ed20424 100644
--- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfiguration.java
+++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfiguration.java
@@ -88,16 +88,17 @@ import org.springframework.util.StringUtils;
* The default shell authentication method uses a username and password combination. If no
* configuration is provided the default username is 'user' and the password will be
* printed to console during application startup. Those default values can be overridden
- * by using {@code shell.auth.simple.username} and {@code shell.auth.simple.password}.
+ * by using {@code management.shell.auth.simple.username} and
+ * {@code management.shell.auth.simple.password}.
*
* 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} is set to
- * {@code spring} or if no explicit {@code shell.auth} 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
+ * Security. This authentication method will get enabled if {@code management.shell.auth.type}
+ * is set to {@code spring} or if no explicit {@code management.shell.auth} 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 ManagementServerProperties}. Required roles can be overridden by
- * {@code shell.auth.spring.roles}.
+ * {@code management.shell.auth.spring.roles}.
*
* 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
@@ -109,7 +110,7 @@ import org.springframework.util.StringUtils;
* crashub.org. By default Boot will search for
* commands using the following classpath scanning pattern {@code classpath*:/commands/**}
* . To add different locations or override the default use
- * {@code shell.command_path_patterns} in your application configuration.
+ * {@code management.shell.command-path-patterns} in your application configuration.
*
* @author Christian Dupuis
* @author Matt Benson
@@ -122,6 +123,8 @@ import org.springframework.util.StringUtils;
ManagementWebSecurityAutoConfiguration.class })
public class CrshAutoConfiguration {
+ public static final String AUTH_PREFIX = ShellProperties.SHELL_PREFIX + ".auth";
+
private final ShellProperties properties;
public CrshAutoConfiguration(ShellProperties properties) {
@@ -140,21 +143,21 @@ public class CrshAutoConfiguration {
static class CrshAdditionalPropertiesConfiguration {
@Bean
- @ConditionalOnProperty(prefix = "shell", name = "auth", havingValue = "jaas")
+ @ConditionalOnProperty(prefix = AUTH_PREFIX, name = "type", havingValue = "jaas")
@ConditionalOnMissingBean(CrshShellAuthenticationProperties.class)
public JaasAuthenticationProperties jaasAuthenticationProperties() {
return new JaasAuthenticationProperties();
}
@Bean
- @ConditionalOnProperty(prefix = "shell", name = "auth", havingValue = "key")
+ @ConditionalOnProperty(prefix = AUTH_PREFIX, name = "type", havingValue = "key")
@ConditionalOnMissingBean(CrshShellAuthenticationProperties.class)
public KeyAuthenticationProperties keyAuthenticationProperties() {
return new KeyAuthenticationProperties();
}
@Bean
- @ConditionalOnProperty(prefix = "shell", name = "auth", havingValue = "simple", matchIfMissing = true)
+ @ConditionalOnProperty(prefix = AUTH_PREFIX, name = "type", havingValue = "simple", matchIfMissing = true)
@ConditionalOnMissingBean(CrshShellAuthenticationProperties.class)
public SimpleAuthenticationProperties simpleAuthenticationProperties() {
return new SimpleAuthenticationProperties();
@@ -166,7 +169,7 @@ public class CrshAutoConfiguration {
* Class to configure CRaSH to authenticate against Spring Security.
*/
@Configuration
- @ConditionalOnProperty(prefix = "shell", name = "auth", havingValue = "spring", matchIfMissing = true)
+ @ConditionalOnProperty(prefix = AUTH_PREFIX, name = "type", havingValue = "spring", matchIfMissing = true)
@ConditionalOnBean(AuthenticationManager.class)
public static class AuthenticationManagerAdapterConfiguration {
@@ -185,12 +188,12 @@ public class CrshAutoConfiguration {
@Bean
@ConditionalOnMissingBean(CrshShellAuthenticationProperties.class)
public SpringAuthenticationProperties springAuthenticationProperties() {
- // In case no shell.auth.type property is provided fall back to Spring Security
- // based authentication and get role to access shell from
+ // In case no management.shell.auth.type property is provided fall back to
+ // Spring Security based authentication and get role to access shell from
// ManagementServerProperties.
- // In case shell.auth.type is set to spring and roles are configured using
- // shell.auth.spring.roles the below default role will be overridden by
- // ConfigurationProperties.
+ // In case management.shell.auth.type is set to spring and roles are
+ // configured using shell.auth.spring.roles the below default role will be
+ // overridden by ConfigurationProperties.
SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
if (this.management != null) {
authenticationProperties.setRoles(
diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ShellProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ShellProperties.java
index ffa10c66ae..c3981ea1b5 100644
--- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ShellProperties.java
+++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ShellProperties.java
@@ -37,10 +37,13 @@ import org.springframework.util.StringUtils;
* @author Christian Dupuis
* @author Phillip Webb
* @author Eddú Meléndez
+ * @author Stephane Nicoll
*/
-@ConfigurationProperties(prefix = "shell", ignoreUnknownFields = true)
+@ConfigurationProperties(prefix = ShellProperties.SHELL_PREFIX, ignoreUnknownFields = true)
public class ShellProperties {
+ public static final String SHELL_PREFIX = "management.shell";
+
private static final Log logger = LogFactory.getLog(ShellProperties.class);
private final Auth auth = new Auth();
@@ -372,7 +375,7 @@ public class ShellProperties {
/**
* Auth specific properties for JAAS authentication.
*/
- @ConfigurationProperties(prefix = "shell.auth.jaas", ignoreUnknownFields = false)
+ @ConfigurationProperties(prefix = SHELL_PREFIX + ".auth.jaas", ignoreUnknownFields = false)
public static class JaasAuthenticationProperties
extends CrshShellAuthenticationProperties {
@@ -401,7 +404,7 @@ public class ShellProperties {
/**
* Auth specific properties for key authentication.
*/
- @ConfigurationProperties(prefix = "shell.auth.key", ignoreUnknownFields = false)
+ @ConfigurationProperties(prefix = SHELL_PREFIX + ".auth.key", ignoreUnknownFields = false)
public static class KeyAuthenticationProperties
extends CrshShellAuthenticationProperties {
@@ -432,7 +435,7 @@ public class ShellProperties {
/**
* Auth specific properties for simple authentication.
*/
- @ConfigurationProperties(prefix = "shell.auth.simple", ignoreUnknownFields = false)
+ @ConfigurationProperties(prefix = SHELL_PREFIX + ".auth.simple", ignoreUnknownFields = false)
public static class SimpleAuthenticationProperties
extends CrshShellAuthenticationProperties {
@@ -508,7 +511,7 @@ public class ShellProperties {
/**
* Auth specific properties for Spring authentication.
*/
- @ConfigurationProperties(prefix = "shell.auth.spring", ignoreUnknownFields = false)
+ @ConfigurationProperties(prefix = SHELL_PREFIX + ".auth.spring", ignoreUnknownFields = false)
public static class SpringAuthenticationProperties
extends CrshShellAuthenticationProperties {
diff --git a/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index d67373739a..8ce47a4b0b 100644
--- a/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -255,7 +255,7 @@
]
},
{
- "name": "shell.auth.type",
+ "name": "management.shell.auth.type",
"values": [
{
"value": "simple",
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfigurationTests.java
index 09910bdb7b..973b8e573e 100644
--- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfigurationTests.java
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CrshAutoConfigurationTests.java
@@ -37,6 +37,7 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
+import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.testutil.Matched;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -64,6 +65,7 @@ import static org.hamcrest.CoreMatchers.isA;
* @author Andreas Ahlenstorf
* @author Eddú Meléndez
* @author Matt Benson
+ * @author Stephane Nicoll
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class CrshAutoConfigurationTests {
@@ -79,10 +81,8 @@ public class CrshAutoConfigurationTests {
@Test
public void testDisabledPlugins() throws Exception {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.disabled_plugins",
+ load("management.shell.disabled_plugins=" +
"termIOHandler, org.crsh.auth.AuthenticationPlugin, javaLanguage");
- load(env);
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
assertThat(lifeCycle).isNotNull();
assertThat(lifeCycle.getContext().getPlugins(TermIOHandler.class))
@@ -98,9 +98,7 @@ public class CrshAutoConfigurationTests {
@Test
public void testAttributes() throws Exception {
- this.context = new AnnotationConfigWebApplicationContext();
- this.context.register(CrshAutoConfiguration.class);
- this.context.refresh();
+ load();
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
Map attributes = lifeCycle.getContext().getAttributes();
assertThat(attributes.containsKey("spring.version")).isTrue();
@@ -111,11 +109,8 @@ public class CrshAutoConfigurationTests {
@Test
public void testSshConfiguration() {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.ssh.enabled", "true");
- env.setProperty("shell.ssh.port", "3333");
- load(env);
-
+ load("management.shell.ssh.enabled=true",
+ "management.shell.ssh.port=3333");
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
assertThat(lifeCycle.getConfig().getProperty("crash.ssh.port")).isEqualTo("3333");
assertThat(lifeCycle.getConfig().getProperty("crash.ssh.auth_timeout"))
@@ -126,10 +121,8 @@ public class CrshAutoConfigurationTests {
@Test
public void testSshConfigurationWithKeyPath() {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.ssh.enabled", "true");
- env.setProperty("shell.ssh.key_path", "~/.ssh/id.pem");
- load(env);
+ load("management.shell.ssh.enabled=true",
+ "management.shell.ssh.key_path=~/.ssh/id.pem");
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
assertThat(lifeCycle.getConfig().getProperty("crash.ssh.keypath"))
.isEqualTo("~/.ssh/id.pem");
@@ -137,11 +130,9 @@ public class CrshAutoConfigurationTests {
@Test
public void testSshConfigurationCustomTimeouts() {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.ssh.enabled", "true");
- env.setProperty("shell.ssh.auth-timeout", "300000");
- env.setProperty("shell.ssh.idle-timeout", "400000");
- load(env);
+ load("management.shell.ssh.enabled=true",
+ "management.shell.ssh.auth-timeout=300000",
+ "management.shell.ssh.idle-timeout=400000");
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
assertThat(lifeCycle.getConfig().getProperty("crash.ssh.auth_timeout"))
.isEqualTo("300000");
@@ -149,18 +140,10 @@ public class CrshAutoConfigurationTests {
.isEqualTo("400000");
}
- private void load(MockEnvironment env) {
- this.context = new AnnotationConfigWebApplicationContext();
- this.context.setEnvironment(env);
- this.context.register(CrshAutoConfiguration.class);
- this.context.refresh();
- }
@Test
public void testCommandResolution() {
- this.context = new AnnotationConfigWebApplicationContext();
- this.context.register(CrshAutoConfiguration.class);
- this.context.refresh();
+ load();
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
int count = 0;
Iterator resources = lifeCycle.getContext()
@@ -182,9 +165,7 @@ public class CrshAutoConfigurationTests {
@Test
public void testDisabledCommandResolution() {
- this.context = new AnnotationConfigWebApplicationContext();
- this.context.register(CrshAutoConfiguration.class);
- this.context.refresh();
+ load();
PluginLifeCycle lifeCycle = this.context.getBean(PluginLifeCycle.class);
int count = 0;
Iterator resources = lifeCycle.getContext()
@@ -229,11 +210,10 @@ public class CrshAutoConfigurationTests {
@Test
public void testJaasAuthenticationProvider() {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.auth.type", "jaas");
- env.setProperty("shell.auth.jaas.domain", "my-test-domain");
this.context = new AnnotationConfigWebApplicationContext();
- this.context.setEnvironment(env);
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "management.shell.auth.type=jaas",
+ "management.shell.auth.jaas.domain=my-test-domain");
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityConfiguration.class);
this.context.register(CrshAutoConfiguration.class);
@@ -246,11 +226,10 @@ public class CrshAutoConfigurationTests {
@Test
public void testKeyAuthenticationProvider() {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.auth.type", "key");
- env.setProperty("shell.auth.key.path", "~/test.pem");
this.context = new AnnotationConfigWebApplicationContext();
- this.context.setEnvironment(env);
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "management.shell.auth.type=key",
+ "management.shell.auth.key.path=~/test.pem");
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityConfiguration.class);
this.context.register(CrshAutoConfiguration.class);
@@ -263,12 +242,11 @@ public class CrshAutoConfigurationTests {
@Test
public void testSimpleAuthenticationProvider() throws Exception {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.auth.type", "simple");
- env.setProperty("shell.auth.simple.user.name", "user");
- env.setProperty("shell.auth.simple.user.password", "password");
this.context = new AnnotationConfigWebApplicationContext();
- this.context.setEnvironment(env);
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "management.shell.auth.type=simple",
+ "management.shell.auth.simple.user.name=user",
+ "management.shell.auth.simple.user.password=password");
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityConfiguration.class);
this.context.register(CrshAutoConfiguration.class);
@@ -293,10 +271,9 @@ public class CrshAutoConfigurationTests {
@Test
public void testSpringAuthenticationProvider() throws Exception {
- MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.auth.type", "spring");
this.context = new AnnotationConfigWebApplicationContext();
- this.context.setEnvironment(env);
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "management.shell.auth.type=spring");
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityConfiguration.class);
this.context.register(CrshAutoConfiguration.class);
@@ -345,6 +322,14 @@ public class CrshAutoConfigurationTests {
SecurityConfiguration.PASSWORD)).isFalse();
}
+ private void load(String... environment) {
+ this.context = new AnnotationConfigWebApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context, environment);
+ this.context.register(CrshAutoConfiguration.class);
+ this.context.refresh();
+ }
+
+
@Configuration
public static class SecurityConfiguration {
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ShellPropertiesTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ShellPropertiesTests.java
index 1f23fd1acb..288a9d9553 100644
--- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ShellPropertiesTests.java
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ShellPropertiesTests.java
@@ -16,26 +16,27 @@
package org.springframework.boot.actuate.autoconfigure;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import org.crsh.plugin.PluginLifeCycle;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
-import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.actuate.autoconfigure.ShellProperties.CrshShellProperties;
import org.springframework.boot.actuate.autoconfigure.ShellProperties.JaasAuthenticationProperties;
import org.springframework.boot.actuate.autoconfigure.ShellProperties.KeyAuthenticationProperties;
import org.springframework.boot.actuate.autoconfigure.ShellProperties.SimpleAuthenticationProperties;
import org.springframework.boot.actuate.autoconfigure.ShellProperties.SpringAuthenticationProperties;
-import org.springframework.boot.bind.RelaxedDataBinder;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.util.EnvironmentTestUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@@ -46,271 +47,206 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ShellProperties}.
*
* @author Christian Dupuis
+ * @author Stephane Nicoll
*/
public class ShellPropertiesTests {
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
@Test
public void testBindingAuth() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.bind(new MutablePropertyValues(
- Collections.singletonMap("shell.auth.type", "spring")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ ShellProperties props = load(ShellProperties.class, "management.shell.auth.type=spring");
assertThat(props.getAuth().getType()).isEqualTo("spring");
}
@Test
public void testBindingAuthIfEmpty() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.bind(
- new MutablePropertyValues(Collections.singletonMap("shell.auth.type", "")));
- assertThat(binder.getBindingResult().hasErrors()).isTrue();
- assertThat(props.getAuth().getType()).isEqualTo("simple");
+ this.thrown.expect(BeanCreationException.class);
+ this.thrown.expectMessage("Auth type must not be empty");
+ load(ShellProperties.class, "management.shell.auth.type= ");
}
@Test
public void testBindingCommandRefreshInterval() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- binder.bind(new MutablePropertyValues(
- Collections.singletonMap("shell.command_refresh_interval", "1")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ ShellProperties props = load(ShellProperties.class, "management.shell.command-refresh-interval=1");
assertThat(props.getCommandRefreshInterval()).isEqualTo(1);
}
@Test
public void testBindingCommandPathPatterns() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- binder.bind(new MutablePropertyValues(Collections
- .singletonMap("shell.command_path_patterns", "pattern1, pattern2")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.command-path-patterns=pattern1, pattern2");
assertThat(props.getCommandPathPatterns().length).isEqualTo(2);
- Assert.assertArrayEquals(new String[] { "pattern1", "pattern2" },
+ Assert.assertArrayEquals(new String[] {"pattern1", "pattern2"},
props.getCommandPathPatterns());
}
@Test
public void testBindingConfigPathPatterns() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- binder.bind(new MutablePropertyValues(Collections
- .singletonMap("shell.config_path_patterns", "pattern1, pattern2")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.config-path-patterns=pattern1, pattern2");
assertThat(props.getConfigPathPatterns().length).isEqualTo(2);
- Assert.assertArrayEquals(new String[] { "pattern1", "pattern2" },
+ Assert.assertArrayEquals(new String[] {"pattern1", "pattern2"},
props.getConfigPathPatterns());
}
@Test
public void testBindingDisabledPlugins() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- binder.bind(new MutablePropertyValues(Collections
- .singletonMap("shell.disabled_plugins", "pattern1, pattern2")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.disabled-plugins=pattern1, pattern2");
assertThat(props.getDisabledPlugins().length).isEqualTo(2);
assertThat(props.getDisabledPlugins()).containsExactly("pattern1", "pattern2");
}
@Test
public void testBindingDisabledCommands() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- binder.bind(new MutablePropertyValues(Collections
- .singletonMap("shell.disabled_commands", "pattern1, pattern2")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.disabled-commands=pattern1, pattern2");
assertThat(props.getDisabledCommands()).containsExactly("pattern1", "pattern2");
}
@Test
public void testBindingSsh() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.ssh.enabled", "true");
- map.put("shell.ssh.port", "2222");
- map.put("shell.ssh.key_path", "~/.ssh/test.pem");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.ssh.enabled=true",
+ "management.shell.ssh.port=2222",
+ "management.shell.ssh.key-path=~/.ssh/test.pem");
Properties p = props.asCrshShellConfig();
-
assertThat(p.get("crash.ssh.port")).isEqualTo("2222");
assertThat(p.get("crash.ssh.keypath")).isEqualTo("~/.ssh/test.pem");
}
@Test
public void testBindingSshIgnored() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.ssh.enabled", "false");
- map.put("shell.ssh.port", "2222");
- map.put("shell.ssh.key_path", "~/.ssh/test.pem");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.ssh.enabled=false",
+ "management.shell.ssh.port=2222",
+ "management.shell.ssh.key-path=~/.ssh/test.pem");
Properties p = props.asCrshShellConfig();
-
assertThat(p.get("crash.ssh.port")).isNull();
assertThat(p.get("crash.ssh.keypath")).isNull();
}
@Test
public void testBindingTelnet() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.telnet.enabled", "true");
- map.put("shell.telnet.port", "2222");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.telnet.enabled=true",
+ "management.shell.telnet.port=2222");
Properties p = props.asCrshShellConfig();
-
assertThat(p.get("crash.telnet.port")).isEqualTo("2222");
}
@Test
public void testBindingTelnetIgnored() {
- ShellProperties props = new ShellProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.telnet.enabled", "false");
- map.put("shell.telnet.port", "2222");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ ShellProperties props = load(ShellProperties.class,
+ "management.shell.telnet.enabled=false",
+ "management.shell.telnet.port=2222");
Properties p = props.asCrshShellConfig();
-
assertThat(p.get("crash.telnet.port")).isNull();
}
@Test
public void testBindingJaas() {
- JaasAuthenticationProperties props = new JaasAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell.auth.jaas");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.auth.jaas.domain", "my-test-domain");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ JaasAuthenticationProperties props = load(JaasAuthenticationProperties.class,
+ "management.shell.auth.jaas.domain=my-test-domain");
Properties p = new Properties();
props.applyToCrshShellConfig(p);
-
assertThat(p.get("crash.auth.jaas.domain")).isEqualTo("my-test-domain");
}
@Test
public void testBindingKey() {
- KeyAuthenticationProperties props = new KeyAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell.auth.key");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.auth.key.path", "~/.ssh/test.pem");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ KeyAuthenticationProperties props = load(KeyAuthenticationProperties.class,
+ "management.shell.auth.key.path=~/.ssh/test.pem");
Properties p = new Properties();
props.applyToCrshShellConfig(p);
-
assertThat(p.get("crash.auth.key.path")).isEqualTo("~/.ssh/test.pem");
}
@Test
public void testBindingKeyIgnored() {
- KeyAuthenticationProperties props = new KeyAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell.auth.key");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ KeyAuthenticationProperties props = load(KeyAuthenticationProperties.class);
Properties p = new Properties();
props.applyToCrshShellConfig(p);
-
assertThat(p.get("crash.auth.key.path")).isNull();
}
@Test
public void testBindingSimple() {
- SimpleAuthenticationProperties props = new SimpleAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell.auth.simple");
- binder.setConversionService(new DefaultConversionService());
- Map map = new HashMap();
- map.put("shell.auth.simple.user.name", "username123");
- map.put("shell.auth.simple.user.password", "password123");
- binder.bind(new MutablePropertyValues(map));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ SimpleAuthenticationProperties props = load(SimpleAuthenticationProperties.class,
+ "management.shell.auth.simple.user.name=username123",
+ "management.shell.auth.simple.user.password=password123");
Properties p = new Properties();
props.applyToCrshShellConfig(p);
-
assertThat(p.get("crash.auth.simple.username")).isEqualTo("username123");
assertThat(p.get("crash.auth.simple.password")).isEqualTo("password123");
}
@Test
- public void testDefaultPasswordAutogeneratedIfUnresolvedPlaceholder() {
- SimpleAuthenticationProperties security = new SimpleAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(security, "security");
- binder.bind(new MutablePropertyValues(Collections
- .singletonMap("shell.auth.simple.user.password", "${ADMIN_PASSWORD}")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ public void testDefaultPasswordAutoGeneratedIfUnresolvedPlaceholder() {
+ SimpleAuthenticationProperties security = load(SimpleAuthenticationProperties.class,
+ "management.shell.auth.simple.user.password=${ADMIN_PASSWORD}");
assertThat(security.getUser().isDefaultPassword()).isTrue();
}
@Test
- public void testDefaultPasswordAutogeneratedIfEmpty() {
- SimpleAuthenticationProperties security = new SimpleAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(security, "security");
- binder.bind(new MutablePropertyValues(
- Collections.singletonMap("shell.auth.simple.user.password", "")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
+ public void testDefaultPasswordAutoGeneratedIfEmpty() {
+ SimpleAuthenticationProperties security = load(SimpleAuthenticationProperties.class,
+ "management.shell.auth.simple.user.password=");
assertThat(security.getUser().isDefaultPassword()).isTrue();
}
@Test
public void testBindingSpring() {
- SpringAuthenticationProperties props = new SpringAuthenticationProperties();
- RelaxedDataBinder binder = new RelaxedDataBinder(props, "shell.auth.spring");
- binder.bind(new MutablePropertyValues(
- Collections.singletonMap("shell.auth.spring.roles", "role1, role2")));
- assertThat(binder.getBindingResult().hasErrors()).isFalse();
-
+ SpringAuthenticationProperties props = load(SpringAuthenticationProperties.class,
+ "management.shell.auth.spring.roles=role1,role2");
Properties p = new Properties();
props.applyToCrshShellConfig(p);
-
assertThat(p.get("crash.auth.spring.roles")).isEqualTo("role1,role2");
}
@Test
public void testCustomShellProperties() throws Exception {
MockEnvironment env = new MockEnvironment();
- env.setProperty("shell.auth.type", "simple");
- AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
- context.setEnvironment(env);
- context.setServletContext(new MockServletContext());
- context.register(TestShellConfiguration.class);
- context.register(CrshAutoConfiguration.class);
- context.refresh();
+ env.setProperty("management.shell.auth.type", "simple");
+ AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
+ ctx.setEnvironment(env);
+ ctx.setServletContext(new MockServletContext());
+ ctx.register(TestShellConfiguration.class);
+ ctx.register(CrshAutoConfiguration.class);
+ ctx.refresh();
- PluginLifeCycle lifeCycle = context.getBean(PluginLifeCycle.class);
+ PluginLifeCycle lifeCycle = ctx.getBean(PluginLifeCycle.class);
String uuid = lifeCycle.getConfig().getProperty("test.uuid");
assertThat(uuid).isEqualTo(TestShellConfiguration.uuid);
- context.close();
+ ctx.close();
+ }
+
+ private T load(Class type, String... environment) {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(ctx, environment);
+ ctx.register(TestConfiguration.class);
+ ctx.refresh();
+ this.context = ctx;
+ return this.context.getBean(type);
+ }
+
+ @Configuration
+ @EnableConfigurationProperties({ShellProperties.class,
+ JaasAuthenticationProperties.class, KeyAuthenticationProperties.class,
+ SimpleAuthenticationProperties.class, SpringAuthenticationProperties.class})
+ static class TestConfiguration {
+
}
@Configuration
diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
index f16d779510..e3cfa60054 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -1007,29 +1007,29 @@ content into your application; rather pick only the properties that you need.
management.info.git.enabled=true # Enable git info.
management.info.git.mode=simple # Mode to use to expose git information.
+ # REMOTE SHELL ({sc-spring-boot-actuator}/autoconfigure/ShellProperties.{sc-ext}[ShellProperties])
+ management.shell.auth.type=simple # Authentication type. Auto-detected according to the environment.
+ management.shell.auth.jaas.domain=my-domain # JAAS domain.
+ management.shell.auth.key.path= # Path to the authentication key. This should point to a valid ".pem" file.
+ management.shell.auth.simple.user.name=user # Login user.
+ management.shell.auth.simple.user.password= # Login password.
+ management.shell.auth.spring.roles=ADMIN # Comma-separated list of required roles to login to the CRaSH console.
+ management.shell.command-path-patterns=classpath*:/commands/**,classpath*:/crash/commands/** # Patterns to use to look for commands.
+ management.shell.command-refresh-interval=-1 # Scan for changes and update the command if necessary (in seconds).
+ management.shell.config-path-patterns=classpath*:/crash/* # Patterns to use to look for configurations.
+ management.shell.disabled-commands=jpa*,jdbc*,jndi* # Comma-separated list of commands to disable.
+ management.shell.disabled-plugins= # Comma-separated list of plugins to disable. Certain plugins are disabled by default based on the environment.
+ management.shell.ssh.auth-timeout = # Number of milliseconds after user will be prompted to login again.
+ management.shell.ssh.enabled=true # Enable CRaSH SSH support.
+ management.shell.ssh.idle-timeout = # Number of milliseconds after which unused connections are closed.
+ management.shell.ssh.key-path= # Path to the SSH server key.
+ management.shell.ssh.port=2000 # SSH port.
+ management.shell.telnet.enabled=false # Enable CRaSH telnet support. Enabled by default if the TelnetPlugin is available.
+ management.shell.telnet.port=5000 # Telnet port.
+
# TRACING ({sc-spring-boot-actuator}/trace/TraceProperties.{sc-ext}[TraceProperties])
management.trace.include=request-headers,response-headers,errors # Items to be included in the trace.
- # REMOTE SHELL
- shell.auth.type=simple # Authentication type. Auto-detected according to the environment.
- shell.auth.jaas.domain=my-domain # JAAS domain.
- shell.auth.key.path= # Path to the authentication key. This should point to a valid ".pem" file.
- shell.auth.simple.user.name=user # Login user.
- shell.auth.simple.user.password= # Login password.
- shell.auth.spring.roles=ADMIN # Comma-separated list of required roles to login to the CRaSH console.
- shell.command-path-patterns=classpath*:/commands/**,classpath*:/crash/commands/** # Patterns to use to look for commands.
- shell.command-refresh-interval=-1 # Scan for changes and update the command if necessary (in seconds).
- shell.config-path-patterns=classpath*:/crash/* # Patterns to use to look for configurations.
- shell.disabled-commands=jpa*,jdbc*,jndi* # Comma-separated list of commands to disable.
- shell.disabled-plugins= # Comma-separated list of plugins to disable. Certain plugins are disabled by default based on the environment.
- shell.ssh.auth-timeout = # Number of milliseconds after user will be prompted to login again.
- shell.ssh.enabled=true # Enable CRaSH SSH support.
- shell.ssh.idle-timeout = # Number of milliseconds after which unused connections are closed.
- shell.ssh.key-path= # Path to the SSH server key.
- shell.ssh.port=2000 # SSH port.
- shell.telnet.enabled=false # Enable CRaSH telnet support. Enabled by default if the TelnetPlugin is available.
- shell.telnet.port=5000 # Telnet port.
-
# METRICS EXPORT ({sc-spring-boot-actuator}/metrics/export/MetricExportProperties.{sc-ext}[MetricExportProperties])
spring.metrics.export.aggregate.key-pattern= # Pattern that tells the aggregator what to do with the keys from the source repository.
spring.metrics.export.aggregate.prefix= # Prefix for global repository if active.
diff --git a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
index 1b0f5b512d..8992129cd4 100644
--- a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
+++ b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
@@ -817,9 +817,10 @@ and `endpoint` commands.
[[production-ready-remote-shell-credentials]]
==== Remote shell credentials
-You can use the `shell.auth.simple.user.name` and `shell.auth.simple.user.password` properties
-to configure custom connection credentials. It is also possible to use a
-'`Spring Security`' `AuthenticationManager` to handle login duties. See the
+You can use the `management.shell.auth.simple.user.name` and
+`management.shell.auth.simple.user.password` properties to configure custom connection
+credentials. It is also possible to use a '`Spring Security`' `AuthenticationManager` to
+handle login duties. See the
{dc-spring-boot-actuator}/autoconfigure/CrshAutoConfiguration.{dc-ext}[`CrshAutoConfiguration`]
and {dc-spring-boot-actuator}/autoconfigure/ShellProperties.{dc-ext}[`ShellProperties`]
Javadoc for full details.
diff --git a/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/resources/application.properties
index d336fdfcb7..23b700c536 100644
--- a/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/resources/application.properties
@@ -1,17 +1,18 @@
-#logging.file: /tmp/logs/app.log
-#server.port: 8080
-#management.port: 8080
-management.address: 127.0.0.1
-endpoints.shutdown.enabled: true
-server.tomcat.basedir: target/tomcat
-server.tomcat.access_log_pattern: %h %t "%r" %s %b
-security.require_ssl: false
-service.name: Daniel
-shell.ssh.enabled: true
-shell.ssh.port: 2222
-#shell.telnet.enabled: false
-#shell.telnet.port: 1111
-shell.auth: spring
-#shell.auth: key
-#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem
-#shell.auth: simple
+#logging.file=/tmp/logs/app.log
+#server.port=8080
+#management.port=8080
+management.address=127.0.0.1
+management.shell.ssh.enabled=true
+management.shell.ssh.port=2222
+#management.shell.telnet.enabled=false
+#management.shell.telnet.port=1111
+management.shell.auth.type=spring
+#management.shell.auth.type=key
+#management.shell.auth.key.path=${user.home}/test/id_rsa.pub.pem
+#management.shell.auth.type=simple
+
+endpoints.shutdown.enabled=true
+server.tomcat.basedir=target/tomcat
+server.tomcat.access_log_pattern=%h %t "%r" %s %b
+security.require_ssl=false
+service.name=Daniel
diff --git a/spring-boot-samples/spring-boot-sample-actuator-noweb/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-actuator-noweb/src/main/resources/application.properties
index 3df2e92ef3..b7fe4cf9e3 100644
--- a/spring-boot-samples/spring-boot-sample-actuator-noweb/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-actuator-noweb/src/main/resources/application.properties
@@ -1,5 +1,6 @@
-service.name: Phil
-shell.ssh.enabled: true
-shell.ssh.port: 2222
-shell.auth: simple
-shell.auth.simple.user.password: password
+service.name=Phil
+
+management.shell.ssh.enabled=true
+management.shell.ssh.port=2222
+management.shell.auth.type=simple
+management.shell.auth.simple.user.password=password
diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
index 8b0f97f092..01a63220a3 100644
--- a/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
@@ -1,28 +1,29 @@
-# logging.file: /tmp/logs/app.log
-# logging.level.org.springframework.security: DEBUG
-management.address: 127.0.0.1
-#management.port: 8181
-endpoints.shutdown.enabled: true
-server.tomcat.basedir: target/tomcat
-server.tomcat.access_log_enabled: true
-server.tomcat.access_log_pattern: %h %t "%r" %s %b
-security.require_ssl: false
-service.name: Phil
-#spring.jackson.serialization.INDENT_OUTPUT: true
-shell.ssh.enabled: true
-shell.ssh.port: 2222
-#shell.telnet.enabled: false
-#shell.telnet.port: 1111
-shell.auth: spring
-#shell.auth: key
-#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem
-#shell.auth: simple
-spring.jmx.enabled: true
-
-spring.jackson.serialization.write_dates_as_timestamps=false
+# logging.file=/tmp/logs/app.log
+# logging.level.org.springframework.security=DEBUG
+management.address=127.0.0.1
+#management.port=8181
+management.shell.ssh.enabled=true
+management.shell.ssh.port=2222
+#management.shell.telnet.enabled=false
+#management.shell.telnet.port=1111
+management.shell.auth.type=spring
+#management.shell.auth.type=key
+#management.shell.auth.key.path=${user.home}/test/id_rsa.pub.pem
+#management.shell.auth.type=simple
management.info.build.mode=full
+endpoints.shutdown.enabled=true
+server.tomcat.basedir=target/tomcat
+server.tomcat.access_log_enabled=true
+server.tomcat.access_log_pattern=%h %t "%r" %s %b
+security.require_ssl=false
+service.name=Phil
+#spring.jackson.serialization.INDENT_OUTPUT=true
+spring.jmx.enabled=true
+
+spring.jackson.serialization.write_dates_as_timestamps=false
+
management.trace.include=REQUEST_HEADERS,RESPONSE_HEADERS,ERRORS,PATH_INFO,\
PATH_TRANSLATED,CONTEXT_PATH,USER_PRINCIPAL,PARAMETERS,QUERY_STRING,AUTH_TYPE,\
REMOTE_ADDRESS,SESSION_ID,REMOTE_USER