Skip to content

Commit

Permalink
always registers the client RestTemplate, even if oauth2 properties a…
Browse files Browse the repository at this point in the history
…re missing (#414)

* Bumps Spring Boot version to 3.2.5
* Some code cleanup
* Registers the client RestTemplate, even if oauth2 properties are missing

Signed-off-by: kvmw <mshamsi@vmware.com>
  • Loading branch information
kvmw committed Apr 19, 2024
1 parent ac8f56f commit 5fef3ca
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 40 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version=4.1.2-SNAPSHOT
parallel=true

springCloudVersion=2023.0.1
springBootVersion=3.2.4
springBootVersion=3.2.5
javaCfenvVersion=3.1.5
nohttpVersion=0.0.11
wireMockVersion=3.5.2
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
package io.pivotal.spring.cloud.config.client;

import org.apache.commons.logging.Log;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.context.config.*;
import org.springframework.boot.context.config.ConfigDataLocation;
import org.springframework.boot.context.config.ConfigDataLocationNotFoundException;
import org.springframework.boot.context.config.ConfigDataLocationResolver;
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
import org.springframework.boot.context.config.Profiles;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.cloud.config.client.ConfigClientRequestTemplateFactory;
Expand All @@ -30,6 +34,8 @@

import java.util.List;

import static io.pivotal.spring.cloud.config.client.ConfigClientOAuth2Properties.PREFIX;

/**
* Using oauth2 properties to configure an authorization interceptor for the
* <code>RestTemplate</code> that calls config server.
Expand All @@ -44,13 +50,13 @@
* {@link ConfigResourceClientAutoConfiguration} and
* {@link VaultTokenRenewalAutoConfiguration} after application startup.
*/
public class ConfigClientOAuth2ConfigDataLocationResolver
public class OAuth2ConfigDataLocationResolver
implements ConfigDataLocationResolver<ConfigServerConfigDataResource>, Ordered {

private final Log log;

public ConfigClientOAuth2ConfigDataLocationResolver(DeferredLogFactory factory) {
this.log = factory.getLog(ConfigClientOAuth2ConfigDataLocationResolver.class);
public OAuth2ConfigDataLocationResolver(DeferredLogFactory factory) {
this.log = factory.getLog(OAuth2ConfigDataLocationResolver.class);
}

@Override
Expand All @@ -65,34 +71,29 @@ public boolean isResolvable(ConfigDataLocationResolverContext resolverContext, C
return false;
}

var oAuth2Properties = binder.bind(ConfigClientOAuth2Properties.PREFIX, ConfigClientOAuth2Properties.class)
.orElse(null);
if (oAuth2Properties == null) {
log.warn("Config Client oauth2 properties are missing. Skipping the auth interceptor configuration");
return false;
}

var bootstrapContext = resolverContext.getBootstrapContext();

// Register the oauth2 properties
bootstrapContext.registerIfAbsent(ConfigClientOAuth2Properties.class,
BootstrapRegistry.InstanceSupplier.of(oAuth2Properties).withScope(BootstrapRegistry.Scope.PROTOTYPE));

// Register the custom factory with oauth2 interceptor.
bootstrapContext.registerIfAbsent(ConfigClientRequestTemplateFactory.class,
context -> new ConfigClientOAuth2RequestTemplateFactory(this.log,
context.get(ConfigClientProperties.class), oAuth2Properties));
var oAuth2Properties = binder.bind(PREFIX, ConfigClientOAuth2Properties.class).orElse(null);
if (oAuth2Properties != null) {
// Register the custom factory with oauth2 interceptor.
bootstrapContext.registerIfAbsent(ConfigClientRequestTemplateFactory.class,
context -> new OAuth2ConfigClientRequestTemplateFactory(this.log,
context.get(ConfigClientProperties.class), oAuth2Properties));
}
else {
log.warn("Config Client oauth2 properties are missing. Skipping the auth interceptor configuration");
// Register the default factory.
bootstrapContext.registerIfAbsent(ConfigClientRequestTemplateFactory.class,
context -> new ConfigClientRequestTemplateFactory(this.log,
context.get(ConfigClientProperties.class)));
}

bootstrapContext.addCloseListener(event -> {
var beanFactory = event.getApplicationContext().getBeanFactory();

// Add the RestTemplate as bean, once the startup is finished.
beanFactory.registerSingleton("configClientRestTemplate",
event.getBootstrapContext().get(RestTemplate.class));
event.getApplicationContext()
.getBeanFactory()
.registerSingleton("configClientRestTemplate", event.getBootstrapContext().get(RestTemplate.class));

// Add the OAuth2 Properties as bean, once the startup is finished.
beanFactory.registerSingleton("configClientOAuth2Properties",
event.getBootstrapContext().get(ConfigClientOAuth2Properties.class));
});

return false;
Expand Down Expand Up @@ -120,11 +121,11 @@ public int getOrder() {
return -2;
}

private static class ConfigClientOAuth2RequestTemplateFactory extends ConfigClientRequestTemplateFactory {
private static class OAuth2ConfigClientRequestTemplateFactory extends ConfigClientRequestTemplateFactory {

private final ClientRegistration clientRegistration;

public ConfigClientOAuth2RequestTemplateFactory(Log log, ConfigClientProperties clientProperties,
public OAuth2ConfigClientRequestTemplateFactory(Log log, ConfigClientProperties clientProperties,
ConfigClientOAuth2Properties oAuth2Properties) {
super(log, clientProperties);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
@AutoConfiguration(after = ConfigClientAutoConfiguration.class)
@ConditionalOnBean(ConfigClientProperties.class)
@ConditionalOnProperty(name = "spring.cloud.config.token")
@EnableConfigurationProperties(ConfigClientOAuth2Properties.class)
@EnableConfigurationProperties
@EnableScheduling
public class VaultTokenRenewalAutoConfiguration {

Expand All @@ -61,9 +61,6 @@ public class VaultTokenRenewalAutoConfiguration {

private static final String REFRESH_PATH = "/vault/v1/auth/token/renew-self";

@Value("${spring.cloud.config.token}")
private String vaultToken;

// Default to a 300 second (5 minute) TTL
@Value("${vault.token.ttl:300000}")
long ttl;
Expand All @@ -75,19 +72,19 @@ public VaultTokenRefresher vaultTokenRefresher(
ConfigClientProperties configClientProperties) {

var refreshUri = configClientProperties.getUri()[0] + REFRESH_PATH;
var obscuredToken = this.vaultToken.substring(0, 4) + "[*]"
+ this.vaultToken.substring(this.vaultToken.length() - 4);
String vaultToken = configClientProperties.getToken();
var obscuredToken = vaultToken.substring(0, 4) + "[*]" + vaultToken.substring(vaultToken.length() - 4);

return new VaultTokenRefresher(configClientRestTemplate, obscuredToken, ttl, refreshUri,
buildTokenRenewRequest());
buildTokenRenewRequest(vaultToken));
}

private HttpEntity<Map<String, Long>> buildTokenRenewRequest() {
private HttpEntity<Map<String, Long>> buildTokenRenewRequest(String vaultToken) {
// convert to seconds, since that's what Vault wants
var ttlInSeconds = this.ttl / 1000;
var requestBody = Map.of("increment", ttlInSeconds);
var headers = new HttpHeaders();
headers.set(VAULT_TOKEN_HEADER, this.vaultToken);
headers.set(VAULT_TOKEN_HEADER, vaultToken);
headers.setContentType(MediaType.APPLICATION_JSON);

return new HttpEntity<>(requestBody, headers);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
org.springframework.boot.context.config.ConfigDataLocationResolver=\
io.pivotal.spring.cloud.config.client.ConfigClientOAuth2ConfigDataLocationResolver
io.pivotal.spring.cloud.config.client.OAuth2ConfigDataLocationResolver

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
io.pivotal.spring.cloud.config.client.ConfigClientOAuth2BootstrapConfiguration
Expand Down

0 comments on commit 5fef3ca

Please sign in to comment.