diff --git a/fiat-api/src/main/java/com/netflix/spinnaker/fiat/shared/FiatAuthenticationConfig.java b/fiat-api/src/main/java/com/netflix/spinnaker/fiat/shared/FiatAuthenticationConfig.java index c4d0a6cd0..81ef5b948 100644 --- a/fiat-api/src/main/java/com/netflix/spinnaker/fiat/shared/FiatAuthenticationConfig.java +++ b/fiat-api/src/main/java/com/netflix/spinnaker/fiat/shared/FiatAuthenticationConfig.java @@ -17,21 +17,14 @@ package com.netflix.spinnaker.fiat.shared; import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; +import static org.springframework.security.config.Customizer.withDefaults; import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.jakewharton.retrofit.Ok3Client; import com.netflix.spinnaker.config.DefaultServiceEndpoint; import com.netflix.spinnaker.config.ErrorConfiguration; -import com.netflix.spinnaker.config.okhttp3.OkHttpClientProvider; -import com.netflix.spinnaker.kork.retrofit.exceptions.SpinnakerRetrofitErrorHandler; +import com.netflix.spinnaker.kork.client.ServiceClientProvider; import com.netflix.spinnaker.kork.web.exceptions.ExceptionMessageDecorator; -import com.netflix.spinnaker.okhttp.SpinnakerRequestInterceptor; -import com.netflix.spinnaker.retrofit.Slf4jRetrofitLogger; -import lombok.Setter; -import lombok.val; -import okhttp3.OkHttpClient; -import org.springframework.beans.factory.annotation.Autowired; +import java.util.Optional; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -40,15 +33,13 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.AuthenticationConverter; -import retrofit.Endpoints; -import retrofit.RestAdapter; -import retrofit.converter.JacksonConverter; @Import(ErrorConfiguration.class) @EnableWebSecurity @@ -58,35 +49,20 @@ @ComponentScan("com.netflix.spinnaker.fiat.shared") public class FiatAuthenticationConfig { - @Autowired(required = false) - @Setter - private RestAdapter.LogLevel retrofitLogLevel = RestAdapter.LogLevel.BASIC; - @Bean @ConditionalOnMissingBean(FiatService.class) // Allows for override public FiatService fiatService( FiatClientConfigurationProperties fiatConfigurationProperties, - SpinnakerRequestInterceptor interceptor, - OkHttpClientProvider okHttpClientProvider) { + ServiceClientProvider provider, + Optional maybeBuilder) { // New role providers break deserialization if this is not enabled. - val objectMapper = new ObjectMapper(); - objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); - objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - - OkHttpClient okHttpClient = - okHttpClientProvider.getClient( - new DefaultServiceEndpoint("fiat", fiatConfigurationProperties.getBaseUrl())); - - return new RestAdapter.Builder() - .setEndpoint(Endpoints.newFixedEndpoint(fiatConfigurationProperties.getBaseUrl())) - .setRequestInterceptor(interceptor) - .setClient(new Ok3Client(okHttpClient)) - .setConverter(new JacksonConverter(objectMapper)) - .setErrorHandler(SpinnakerRetrofitErrorHandler.getInstance()) - .setLogLevel(retrofitLogLevel) - .setLog(new Slf4jRetrofitLogger(FiatService.class)) - .build() - .create(FiatService.class); + var objectMapper = + maybeBuilder + .orElseGet(Jackson2ObjectMapperBuilder::json) + .featuresToEnable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) + .build(); + var endpoint = new DefaultServiceEndpoint("fiat", fiatConfigurationProperties.getBaseUrl()); + return provider.getService(FiatService.class, endpoint, objectMapper); } /** @@ -138,12 +114,9 @@ private FiatWebSecurityConfigurerAdapter( @Override protected void configure(HttpSecurity http) throws Exception { - http.servletApi() - .and() - .exceptionHandling() - .and() - .anonymous() - .and() + http.servletApi(withDefaults()) + .exceptionHandling(withDefaults()) + .anonymous(anonymous -> anonymous.principal("anonymous")) .addFilterBefore( new FiatAuthenticationFilter(fiatStatus, authenticationConverter), AnonymousAuthenticationFilter.class); diff --git a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/Main.java b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/Main.java index f95903ab4..f9137739b 100644 --- a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/Main.java +++ b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/Main.java @@ -16,7 +16,6 @@ package com.netflix.spinnaker.fiat; -import com.netflix.spinnaker.config.ErrorConfiguration; import com.netflix.spinnaker.kork.boot.DefaultPropertiesBuilder; import java.util.Map; import org.springframework.boot.actuate.autoconfigure.ldap.LdapHealthContributorAutoConfiguration; @@ -27,7 +26,6 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling @@ -36,7 +34,6 @@ "com.netflix.spinnaker.fiat", "com.netflix.spinnaker.config", }) -@Import(ErrorConfiguration.class) @EnableAutoConfiguration( exclude = { GsonAutoConfiguration.class, diff --git a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/FiatConfig.java b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/FiatConfig.java index 9b74d0b74..e67a7327b 100644 --- a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/FiatConfig.java +++ b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/FiatConfig.java @@ -1,6 +1,5 @@ package com.netflix.spinnaker.fiat.config; -import com.google.common.collect.ImmutableList; import com.netflix.spectator.api.Registry; import com.netflix.spinnaker.config.PluginsAutoConfiguration; import com.netflix.spinnaker.fiat.model.Authorization; @@ -24,7 +23,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import lombok.val; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -40,19 +38,19 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @Import({RetrofitConfig.class, PluginsAutoConfiguration.class}) @EnableConfigurationProperties(FiatServerConfigurationProperties.class) -public class FiatConfig extends WebMvcConfigurerAdapter { +public class FiatConfig implements WebMvcConfigurer { @Autowired private Registry registry; @Override public void addInterceptors(InterceptorRegistry registry) { - var pathVarsToTag = ImmutableList.of("accountName", "applicationName", "resourceName"); - List exclude = ImmutableList.of("BasicErrorController"); + var pathVarsToTag = List.of("accountName", "applicationName", "resourceName"); + List exclude = List.of("BasicErrorController"); MetricsInterceptor interceptor = new MetricsInterceptor(this.registry, "controller.invocations", pathVarsToTag, exclude); registry.addInterceptor(interceptor); @@ -60,8 +58,7 @@ public void addInterceptors(InterceptorRegistry registry) { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { - super.configureContentNegotiation(configurer); - configurer.favorPathExtension(false).defaultContentType(MediaType.APPLICATION_JSON); + configurer.defaultContentType(MediaType.APPLICATION_JSON); } @Bean @@ -123,11 +120,11 @@ public DefaultServiceAccountPredicateProvider defaultServiceAccountPredicateProv /** * This AuthenticatedRequestFilter pulls the email and accounts out of the Spring security context - * in order to enabling forwarding them to downstream components. + * in order to enable forwarding them to downstream components. */ @Bean - FilterRegistrationBean authenticatedRequestFilter() { - val frb = new FilterRegistrationBean(new AuthenticatedRequestFilter(true)); + FilterRegistrationBean authenticatedRequestFilter() { + var frb = new FilterRegistrationBean<>(new AuthenticatedRequestFilter(true)); frb.setOrder(Ordered.LOWEST_PRECEDENCE); return frb; } diff --git a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/ResourcesConfig.java b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/ResourcesConfig.java index d10582a39..ab167fc2a 100644 --- a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/ResourcesConfig.java +++ b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/ResourcesConfig.java @@ -16,16 +16,11 @@ package com.netflix.spinnaker.fiat.config; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.jakewharton.retrofit.Ok3Client; import com.netflix.spinnaker.config.DefaultServiceEndpoint; -import com.netflix.spinnaker.config.okhttp3.OkHttpClientProvider; import com.netflix.spinnaker.fiat.providers.ProviderHealthTracker; import com.netflix.spinnaker.fiat.providers.internal.*; -import com.netflix.spinnaker.kork.retrofit.exceptions.SpinnakerRetrofitErrorHandler; -import com.netflix.spinnaker.retrofit.Slf4jRetrofitLogger; -import lombok.Setter; -import org.springframework.beans.factory.annotation.Autowired; +import com.netflix.spinnaker.kork.client.ServiceClientProvider; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -35,45 +30,18 @@ import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.Scope; -import retrofit.Endpoints; -import retrofit.RestAdapter; -import retrofit.converter.JacksonConverter; @Configuration @EnableConfigurationProperties(ProviderCacheConfig.class) @PropertySource("classpath:resilience4j-defaults.properties") +@RequiredArgsConstructor public class ResourcesConfig { - @Autowired @Setter private RestAdapter.LogLevel retrofitLogLevel; - - @Autowired @Setter private ObjectMapper objectMapper; - - @Autowired @Setter private OkHttpClientProvider clientProvider; - - @Value("${services.front50.base-url}") - @Setter - private String front50Endpoint; - - @Value("${services.clouddriver.base-url}") - @Setter - private String clouddriverEndpoint; - - @Value("${services.igor.base-url}") - @Setter - private String igorEndpoint; + private final ServiceClientProvider provider; @Bean - Front50Api front50Api() { - return new RestAdapter.Builder() - .setEndpoint(Endpoints.newFixedEndpoint(front50Endpoint)) - .setClient( - new Ok3Client( - clientProvider.getClient(new DefaultServiceEndpoint("front50", front50Endpoint)))) - .setConverter(new JacksonConverter(objectMapper)) - .setErrorHandler(SpinnakerRetrofitErrorHandler.getInstance()) - .setLogLevel(retrofitLogLevel) - .setLog(new Slf4jRetrofitLogger(Front50Api.class)) - .build() - .create(Front50Api.class); + Front50Api front50Api(@Value("${services.front50.base-url}") String front50Endpoint) { + return provider.getService( + Front50Api.class, new DefaultServiceEndpoint("front50", front50Endpoint)); } @Bean @@ -96,19 +64,10 @@ Front50Service front50Service( } @Bean - ClouddriverApi clouddriverApi() { - return new RestAdapter.Builder() - .setEndpoint(Endpoints.newFixedEndpoint(clouddriverEndpoint)) - .setClient( - new Ok3Client( - clientProvider.getClient( - new DefaultServiceEndpoint("clouddriver", clouddriverEndpoint)))) - .setConverter(new JacksonConverter(objectMapper)) - .setErrorHandler(SpinnakerRetrofitErrorHandler.getInstance()) - .setLogLevel(retrofitLogLevel) - .setLog(new Slf4jRetrofitLogger(ClouddriverApi.class)) - .build() - .create(ClouddriverApi.class); + ClouddriverApi clouddriverApi( + @Value("${services.clouddriver.base-url}") String clouddriverEndpoint) { + return provider.getService( + ClouddriverApi.class, new DefaultServiceEndpoint("clouddriver", clouddriverEndpoint)); } @Bean @@ -154,17 +113,7 @@ ClouddriverService clouddriverServiceWithoutApplicationLoader( @Bean @ConditionalOnProperty("services.igor.enabled") IgorApi igorApi(@Value("${services.igor.base-url}") String igorEndpoint) { - return new RestAdapter.Builder() - .setEndpoint(Endpoints.newFixedEndpoint(igorEndpoint)) - .setClient( - new Ok3Client( - clientProvider.getClient(new DefaultServiceEndpoint("igor", igorEndpoint)))) - .setConverter(new JacksonConverter(objectMapper)) - .setErrorHandler(SpinnakerRetrofitErrorHandler.getInstance()) - .setLogLevel(retrofitLogLevel) - .setLog(new Slf4jRetrofitLogger(IgorApi.class)) - .build() - .create(IgorApi.class); + return provider.getService(IgorApi.class, new DefaultServiceEndpoint("igor", igorEndpoint)); } @Bean diff --git a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/RetrofitConfig.java b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/RetrofitConfig.java index 102195fce..a08031e7c 100644 --- a/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/RetrofitConfig.java +++ b/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/RetrofitConfig.java @@ -17,14 +17,11 @@ package com.netflix.spinnaker.fiat.config; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.collect.ImmutableList; import java.io.IOException; import java.util.List; import lombok.AllArgsConstructor; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; import okhttp3.Interceptor; import okhttp3.Request; @@ -33,37 +30,19 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.util.backoff.BackOffExecution; import org.springframework.util.backoff.ExponentialBackOff; import retrofit.RestAdapter; -/** This package is placed in fiat-core in order to be shared by fiat-web and fiat-shared. */ +/** Provides base beans used for configuring Retrofit REST client facades. */ @Configuration public class RetrofitConfig { - @Value("${ok-http-client.connection-pool.max-idle-connections:5}") - @Setter - private int maxIdleConnections; - - @Value("${ok-http-client.connection-pool.keep-alive-duration-ms:300000}") - @Setter - private int keepAliveDurationMs; - - @Value("${ok-http-client.retry-on-connection-failure:true}") - @Setter - private boolean retryOnConnectionFailure; - - @Value("${ok-http-client.retries.max-elapsed-backoff-ms:5000}") - @Setter - private long maxElapsedBackoffMs; - @Bean @Primary - ObjectMapper objectMapper() { - return new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .configure(SerializationFeature.INDENT_OUTPUT, true) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); + ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { + return builder.serializationInclusion(JsonInclude.Include.NON_NULL).indentOutput(true).build(); } @Bean @@ -72,7 +51,8 @@ RestAdapter.LogLevel retrofitLogLevel(@Value("${retrofit.log-level:BASIC}") Stri } @Bean - RetryingInterceptor retryingInterceptor() { + RetryingInterceptor retryingInterceptor( + @Value("${ok-http-client.retries.max-elapsed-backoff-ms:5000}") long maxElapsedBackoffMs) { return new RetryingInterceptor(maxElapsedBackoffMs); }