Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
package org.springframework.cloud.config.server.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.config.server.encryption.EncryptionController;
import org.springframework.cloud.config.server.encryption.TextEncryptorLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/**
* @author Bartosz Wojtkiewicz
Expand All @@ -36,11 +38,18 @@ public class ConfigServerEncryptionConfiguration {
@Autowired
private ConfigServerProperties properties;

@Autowired
private Environment environment;

@Bean
public EncryptionController encryptionController() {
Comment thread
dsyer marked this conversation as resolved.
EncryptionController controller = new EncryptionController(this.encryptor);
controller.setDefaultApplicationName(this.properties.getDefaultApplicationName());
controller.setDefaultProfile(this.properties.getDefaultProfile());
boolean validateProfiles = Binder.get(this.environment)
.bind("spring.profiles.validate", Boolean.class)
.orElse(true);
controller.setValidateProfiles(validateProfiles);
return controller;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.config.server.encryption.EnvironmentEncryptor;
import org.springframework.cloud.config.server.encryption.ResourceEncryptor;
import org.springframework.cloud.config.server.environment.EnvironmentController;
Expand All @@ -38,6 +39,7 @@
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
Expand Down Expand Up @@ -74,6 +76,14 @@ static class EnvironmentControllerConfiguration {
@Autowired(required = false)
private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;

private boolean validateProfiles = true;

EnvironmentControllerConfiguration(Environment environment) {
this.validateProfiles = Binder.get(environment)
.bind("spring.profiles.validate", Boolean.class)
.orElse(true);
}

@Bean
public EnvironmentController environmentController(EnvironmentRepository envRepository,
ConfigServerProperties server) {
Expand All @@ -86,6 +96,7 @@ protected EnvironmentController delegateController(EnvironmentRepository envRepo
this.objectMapper);
controller.setStripDocumentFromYaml(server.isStripDocumentFromYaml());
controller.setAcceptEmpty(server.isAcceptEmpty());
controller.setValidateProfiles(this.validateProfiles);
return controller;
}

Expand All @@ -97,6 +108,7 @@ public ResourceController resourceController(ResourceRepository repository, Envi
this.resourceEncryptorMap);
controller.setEncryptEnabled(server.getEncrypt().isEnabled());
controller.setPlainTextEncryptEnabled(server.getEncrypt().isPlainTextEncrypt());
controller.setValidateProfiles(this.validateProfiles);
return controller;
}

Expand All @@ -119,6 +131,10 @@ private EnvironmentRepository encrypted(EnvironmentRepository envRepository, Con
@ConditionalOnBean(org.springframework.cloud.context.scope.refresh.RefreshScope.class)
static class RefreshableEnvironmentControllerConfiguration extends EnvironmentControllerConfiguration {

RefreshableEnvironmentControllerConfiguration(Environment environment) {
super(environment);
}

@Override
@Bean
@RefreshScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public class EncryptionController {

private String defaultProfile = "default";

private boolean validateProfiles = true;

public EncryptionController(TextEncryptorLocator encryptorLocator) {
this.encryptorLocator = encryptorLocator;
}
Expand Down Expand Up @@ -151,7 +153,7 @@ private TextEncryptor getEncryptor(String name, String profiles, String data) {
if (isInvalidEncodedLocation(name)) {
throw new InvalidEnvironmentRequestException("Invalid request");
}
if (isInvalidProfiles(profiles)) {
if (this.validateProfiles && isInvalidProfiles(profiles)) {
throw new InvalidEnvironmentRequestException("Invalid request");
}

Expand Down Expand Up @@ -266,6 +268,10 @@ public ResponseEntity<Map<String, Object>> invalidCipher() {
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}

public void setValidateProfiles(boolean validateProfiles) {
this.validateProfiles = validateProfiles;
}

}

@SuppressWarnings("serial")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ public class EnvironmentController {

private boolean acceptEmpty = true;

private boolean validateProfiles = true;

public EnvironmentController(EnvironmentRepository repository) {
this(repository, new JsonMapper());
}
Expand All @@ -105,6 +107,15 @@ public void setAcceptEmpty(boolean acceptEmpty) {
this.acceptEmpty = acceptEmpty;
}

/**
* Flag to indicate that spring profiles are to be validated (default true). If set to
* false, then profiles with invalid characters (e.g. '-') will throw an exception.
* @param validateProfiles the flag to set
*/
public void setValidateProfiles(boolean validateProfiles) {
this.validateProfiles = validateProfiles;
}

@GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",
produces = MediaType.APPLICATION_JSON_VALUE)
public Environment defaultLabel(@PathVariable String name, @PathVariable String profiles) {
Expand Down Expand Up @@ -132,7 +143,7 @@ public Environment getEnvironment(String name, String profiles, String label, bo
try {
name = normalize(name);
label = normalize(label);
if (isInvalidProfiles(profiles)) {
if (this.validateProfiles && isInvalidProfiles(profiles)) {
throw new InvalidEnvironmentRequestException("Invalid request");
}
Environment environment = this.repository.findOne(name, profiles, label, includeOrigin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public class ResourceController {

private boolean plainTextEncryptEnabled = false;

private boolean validateProfiles = true;

public ResourceController(ResourceRepository resourceRepository, EnvironmentRepository environmentRepository,
Map<String, ResourceEncryptor> resourceEncryptorMap) {
this.resourceRepository = resourceRepository;
Expand All @@ -104,6 +106,15 @@ public void setPlainTextEncryptEnabled(boolean plainTextEncryptEnabled) {
this.plainTextEncryptEnabled = plainTextEncryptEnabled;
}

/**
* Flag to indicate that spring profiles are to be validated (default true). If set to
* false, then profiles with invalid characters (e.g. '-') will throw an exception.
* @param validateProfiles the flag to set
*/
public void setValidateProfiles(boolean validateProfiles) {
this.validateProfiles = validateProfiles;
}

@GetMapping("/{name}/{profile}/{label}/**")
public String retrieve(@PathVariable String name, @PathVariable String profile, @PathVariable String label,
ServletWebRequest request, @RequestParam(defaultValue = "true") boolean resolvePlaceholders,
Expand Down Expand Up @@ -145,7 +156,7 @@ synchronized String retrieve(ServletWebRequest request, String name, String prof
boolean resolvePlaceholders, String acceptedCharset) throws IOException {
name = normalize(name);
label = normalize(label);
if (isInvalidProfiles(profile)) {
if (this.validateProfiles && isInvalidProfiles(profile)) {
throw new InvalidEnvironmentRequestException("Invalid request");
}
path = normalize(path);
Expand Down Expand Up @@ -227,7 +238,7 @@ private synchronized byte[] binary(ServletWebRequest request, String name, Strin
String path) throws IOException {
name = normalize(name);
label = normalize(label);
if (isInvalidProfiles(profile)) {
if (this.validateProfiles && isInvalidProfiles(profile)) {
throw new InvalidEnvironmentRequestException("Invalid request");
}
path = normalize(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.springframework.web.util.pattern.PathPatternParser;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -580,6 +581,12 @@ public void invalidProfileTests() {
.isInstanceOf(InvalidEnvironmentRequestException.class);
}

@Test
public void invalidProfileTestsDisabled() {
this.controller.setValidateProfiles(false);
assertThatNoException().isThrownBy(() -> this.controller.labelled("application", "bar,..,foo", "label"));
}

abstract class MockMvcTestCases {

protected MockMvc mvc;
Expand Down
Loading