From 0c9a2b9b4622e0a28d00adf59fc340c205bd5265 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Mar 2021 15:33:23 +0100 Subject: [PATCH] Reconfigure loggers of Vault client components during ConfigData bootstrap. We now reconfigure loggers through reflection of VaultPropertySource, SecretLeaseContainer and other components to obtain log events during the bootstrap. Closes gh-565. --- .../vault/config/VaultConfigDataLoader.java | 97 +++++++++++++++++-- 1 file changed, 87 insertions(+), 10 deletions(-) diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigDataLoader.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigDataLoader.java index f3c1e4be..a33022c4 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigDataLoader.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigDataLoader.java @@ -17,12 +17,18 @@ package org.springframework.cloud.vault.config; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import org.apache.commons.logging.Log; + import org.springframework.beans.factory.BeanFactory; import org.springframework.boot.BootstrapContext; import org.springframework.boot.BootstrapRegistry; @@ -32,6 +38,7 @@ import org.springframework.boot.context.config.ConfigData; import org.springframework.boot.context.config.ConfigDataLoader; import org.springframework.boot.context.config.ConfigDataLoaderContext; import org.springframework.boot.context.config.ConfigDataLocationNotFoundException; +import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.cloud.vault.config.VaultAutoConfiguration.TaskSchedulerWrapper; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ConfigurableApplicationContext; @@ -39,6 +46,7 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.env.PropertySource; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.reactive.ClientHttpConnector; +import org.springframework.lang.Nullable; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -48,6 +56,7 @@ import org.springframework.vault.authentication.ClientAuthentication; import org.springframework.vault.authentication.ReactiveSessionManager; import org.springframework.vault.authentication.SessionManager; import org.springframework.vault.authentication.VaultTokenSupplier; +import org.springframework.vault.client.ClientHttpRequestFactoryFactory; import org.springframework.vault.client.RestTemplateBuilder; import org.springframework.vault.client.RestTemplateFactory; import org.springframework.vault.client.SimpleVaultEndpointProvider; @@ -92,6 +101,13 @@ public class VaultConfigDataLoader implements ConfigDataLoader> loggers = Arrays.asList(ClientHttpRequestFactoryFactory.class, VaultPropertySource.class, + LeaseAwareVaultPropertySource.class, + forName("org.springframework.vault.core.lease.SecretLeaseContainer$LeaseRenewalScheduler"), + forName("org.springframework.vault.core.lease.SecretLeaseEventPublisher$LoggingErrorListener")); + + loggers.forEach(it -> reconfigureLogger(it, logFactory)); + } + + static void reconfigureLogger(Class type, DeferredLogFactory logFactory) { + + ReflectionUtils.doWithFields(type, field -> { + + field.setAccessible(true); + field.set(null, logFactory.getLog(type)); + + }, VaultConfigDataLoader::isUpdateableLogField); + } + + static void reconfigureLogger(Object object, DeferredLogFactory logFactory) { + + ReflectionUtils.doWithFields(object.getClass(), field -> { + + field.setAccessible(true); + field.set(object, logFactory.getLog(object.getClass())); + + }, VaultConfigDataLoader::isUpdateableLogField); + } + + static boolean isUpdateableLogField(Field field) { + return !Modifier.isFinal(field.getModifiers()) && field.getType().isAssignableFrom(Log.class); + } + + @Nullable + static Class forName(String name) { + try { + return ClassUtils.forName(name, VaultConfigDataLocationResolver.class.getClassLoader()); + } + catch (ClassNotFoundException e) { + return null; + } + } + /** * Support class to register imperative infrastructure bootstrap instances and beans. * @@ -366,11 +427,15 @@ public class VaultConfigDataLoader implements ConfigDataLoader this.configuration.createSessionManager(ctx.get(ClientAuthentication.class), - () -> ctx.get(TaskSchedulerWrapper.class).getTaskScheduler(), - ctx.get(RestTemplateFactory.class))); + registerIfAbsent(this.bootstrap, "vaultSessionManager", SessionManager.class, ctx -> { + SessionManager sessionManager = this.configuration.createSessionManager( + ctx.get(ClientAuthentication.class), + () -> ctx.get(TaskSchedulerWrapper.class).getTaskScheduler(), + ctx.get(RestTemplateFactory.class)); + reconfigureLogger(sessionManager, this.logFactory); + return sessionManager; + }); } } @@ -442,11 +511,15 @@ public class VaultConfigDataLoader implements ConfigDataLoader this.configuration.createSessionManager(ctx.get(ReactiveSessionManager.class))); + registerIfAbsent(this.bootstrap, "vaultSessionManager", SessionManager.class, ctx -> { + SessionManager sessionManager = this.configuration + .createSessionManager(ctx.get(ReactiveSessionManager.class)); + reconfigureLogger(sessionManager, this.logFactory); + return sessionManager; + }); } }