Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring Boot 3 Upgrade pt 1 #1512

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
12 changes: 5 additions & 7 deletions aat/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ dependencyCheck {
suppressionFile = "${rootDir}/dependency-check-suppressions.xml"
}

dependencies {
implementation (group: 'com.github.hmcts', name: 'service-auth-provider-java-client', version: '4.0.3') {
exclude group: 'com.google.guava', module: 'guava'
}
implementation group: 'org.awaitility', name: 'awaitility', version: '3.1.6'
}

sourceSets {
aat {
java {
Expand All @@ -29,6 +22,11 @@ sourceSets {
}
}

dependencies {
implementation group: 'com.github.hmcts', name: 'service-auth-provider-java-client', version: '5.2.0'
implementation group: 'org.awaitility', name: 'awaitility', version: '3.1.6'
}

tasks.named("processAatResources") {
duplicatesStrategy = 'include'
}
Expand Down
4 changes: 0 additions & 4 deletions app-insights/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ plugins {
id 'info.solidsoft.pitest'
}

dependencies {
// compile "org.springframework:spring-context:5.0.7.RELEASE"
}

dependencyCheck {
suppressionFile = "${rootDir}/dependency-check-suppressions.xml"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AppInsightsTest {

@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
TelemetryContext telemetryContext = new TelemetryContext();
telemetryContext.setInstrumentationKey("some-key");
doReturn(telemetryContext).when(telemetryClient).getContext();
Expand Down
12 changes: 5 additions & 7 deletions application/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ dependencies {
implementation project(':elastic-search-support')
implementation project(':repository')
implementation project(':domain')
implementation "org.springframework.boot:spring-boot-starter-web"
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation ("io.springfox:springfox-boot-starter:${springfoxSwaggerVersion}") {
exclude group: 'com.google.guava', module: 'guava'
}
implementation "org.flywaydb:flyway-core:6.5.7"
runtimeOnly group: 'org.postgresql', name: 'postgresql', version: '42.7.3'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: springDocVersion
implementation group: 'org.flywaydb', name: 'flyway-core', version: flywayVersion
runtimeOnly group: 'org.postgresql', name: 'postgresql', version: '42.7.4'

testImplementation project(":app-insights").sourceSets.main.output
testImplementation project(":commons").sourceSets.main.output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,33 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders;
import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
// import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.security.web.SecurityFilterChain;

import uk.gov.hmcts.ccd.definition.store.elastic.endpoint.ElasticsearchIndexController;
import uk.gov.hmcts.ccd.definition.store.excel.endpoint.ImportController;
import uk.gov.hmcts.ccd.definition.store.security.JwtGrantedAuthoritiesConverter;
import uk.gov.hmcts.ccd.definition.store.security.filters.ExceptionHandlingFilter;
import uk.gov.hmcts.reform.authorisation.filters.ServiceAuthFilter;

import javax.inject.Inject;
import jakarta.inject.Inject;

import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration
extends WebSecurityConfigurerAdapter {
public class SecurityConfiguration {

@Value("${spring.security.oauth2.client.provider.oidc.issuer-uri}")
private String issuerUri;
Expand All @@ -51,11 +51,12 @@ public SecurityConfiguration(final ServiceAuthFilter serviceAuthFilter,
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
}

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/swagger-resources/**",
@Bean
public WebSecurityCustomizer wewWebSecurityCustomizer() {
return web -> web.ignoring().requestMatchers("/swagger-resources/**",
"/swagger-ui/**",
"/webjars/**",
"/v3/api-docs",
"/v2/**",
"/health",
"/health/liveness",
Expand All @@ -65,27 +66,24 @@ public void configure(WebSecurity web) throws Exception {
"/api/testing-support/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.addFilterBefore(exceptionHandlingFilter, BearerTokenAuthenticationFilter.class)
.addFilterBefore(serviceAuthFilter, BearerTokenAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(STATELESS).and()
.csrf().disable()
.formLogin().disable()
.logout().disable()
.authorizeRequests()
.antMatchers(ImportController.URI_IMPORT, ElasticsearchIndexController.ELASTIC_INDEX_URI)
.hasAuthority("ccd-import")
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter)
.and()
.and()
.csrf(csrf -> csrf.disable()) // NOSONAR - CSRF is disabled as per security requirements
.formLogin(fl -> fl.disable())
.logout(lg -> lg.disable())
.authorizeHttpRequests(ar ->
ar.requestMatchers(ImportController.URI_IMPORT, ElasticsearchIndexController.ELASTIC_INDEX_URI)
.hasAuthority("ccd-import")
.anyRequest()
.authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt().jwtAuthenticationConverter(jwtAuthenticationConverter))
.oauth2Client();
return http.build();
}

@Bean
Expand All @@ -94,7 +92,7 @@ JwtDecoder jwtDecoder() {

// We are using issuerOverride instead of issuerUri as SIDAM has the wrong issuer at the moment
OAuth2TokenValidator<Jwt> withTimestamp = new JwtTimestampValidator();
OAuth2TokenValidator<Jwt> withIssuer = new JwtIssuerValidator(issuerOverride);
// OAuth2TokenValidator<Jwt> withIssuer = new JwtIssuerValidator(issuerOverride);
// FIXME : enable `withIssuer` once idam migration is done RDM-8094
// OAuth2TokenValidator<Jwt> validator = new DelegatingOAuth2TokenValidator<>(withTimestamp, withIssuer);
OAuth2TokenValidator<Jwt> validator = new DelegatingOAuth2TokenValidator<>(withTimestamp);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,67 +1,18 @@
package uk.gov.hmcts.ccd.definition.store;

import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;

@Configuration
public class SwaggerConfiguration {

@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage(CaseDataAPIApplication.class.getPackage().getName()))
.build();
}

//CCD-3509 CVE-2021-22044 required to fix null pointers in integration tests,
//conflict in Springfox after Springboot 2.6.10
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties, Environment environment) {

List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment,
basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
corsProperties.toCorsConfiguration(),
new EndpointLinksResolver(allEndpoints, basePath),
shouldRegisterLinksMapping, null);
}

private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment,
String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("CaseDataAPI Application")
.description("CaseDataAPIApplication"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import jakarta.persistence.EntityManagerFactory;

@Configuration
@EnableTransactionManagement
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
package uk.gov.hmcts.ccd.definition.store.hikari;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.zaxxer.hikari.HikariDataSource;

import java.util.ArrayList;

import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint;
import org.springframework.boot.actuate.endpoint.SanitizingFunction;
import org.springframework.boot.actuate.endpoint.Show;
import org.springframework.stereotype.Component;

// needed to fix "error" : "Cannot serialize 'spring.datasource.hikari'" in actuator /configprops endpoint
// and be able to see configuration properties set for Hikari connection pool
@Component
public class HikariConfigurationPropertiesReportEndpoint extends ConfigurationPropertiesReportEndpoint {

public HikariConfigurationPropertiesReportEndpoint() {
super(new ArrayList<SanitizingFunction>(), Show.ALWAYS);
}

@Override
protected void configureObjectMapper(ObjectMapper mapper) {
super.configureObjectMapper(mapper);
mapper.addMixIn(HikariDataSource.class, HikariDataSourceMixIn.class);
protected void configureJsonMapper(JsonMapper.Builder builder) {
super.configureJsonMapper(builder);
builder.addMixIn(HikariDataSource.class, HikariDataSourceMixIn.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public JwtGrantedAuthoritiesConverter(IdamRepository idamRepository) {
@Override
public Collection<GrantedAuthority> convert(Jwt jwt) {
List<GrantedAuthority> authorities = new ArrayList<>();
if (jwt.containsClaim(TOKEN_NAME) && jwt.getClaim(TOKEN_NAME).equals(ACCESS_TOKEN)) {
if (jwt.hasClaim(TOKEN_NAME) && jwt.getClaim(TOKEN_NAME).equals(ACCESS_TOKEN)) {
UserInfo userInfo = idamRepository.getUserInfo(jwt.getTokenValue());
authorities = extractAuthorityFromClaims(userInfo.getRoles());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
* Used to catch the exceptions thrown in the Spring Security filter chain, except the following ServiceAuthFilter
Expand Down
5 changes: 3 additions & 2 deletions application/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ spring.datasource.hikari.connection-timeout=${DEFINITION_STORE_DB_CONNECTION_TIM
spring.main.allow-bean-definition-overriding=true
# Jackson ObjectMapper configuration
spring.jackson.serialization.write-dates-as-timestamps=false

spring.jpa.properties.hibernate.ejb.interceptor=uk.gov.hmcts.ccd.definition.store.repository.interceptor.CaseRoleInterceptor
hibernate.session_factory.interceptor=uk.gov.hmcts.ccd.definition.store.repository.interceptor.CaseRoleInterceptor
# Disable feature detection to avoid the java.sql.SQLFeatureNotSupportedException
# Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented.
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
Expand All @@ -42,6 +41,8 @@ spring.security.oauth2.client.registration.oidc.client-secret = internal
#required to fix null pointers in integration tests, conflict in Springfox after Springboot 2.6.10 upgrade
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

springdoc.packagesToScan=uk.gov.hmcts.ccd.definition.store

oidc.issuer = ${OIDC_ISSUER:http://fr-am:8080/openam/oauth2/hmcts}

idam.s2s-auth.url=${IDAM_S2S_URL:http://localhost:4502}
Expand Down

This file was deleted.

Loading