Skip to content

Commit

Permalink
Update Springboot to 3.2.2
Browse files Browse the repository at this point in the history
 - Updated SpringBoot to 3.2.2 to fix CVE-2024-22233
 - Fix springboot autoconfiguration config bug in app starter
  • Loading branch information
yinan-symphony committed Feb 1, 2024
1 parent b564165 commit 21e93c4
Show file tree
Hide file tree
Showing 17 changed files with 155 additions and 76 deletions.
7 changes: 7 additions & 0 deletions allow-list.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@
<cve>CVE-2022-45688</cve>
<cve>CVE-2023-5072</cve>
</suppress>
<suppress>
<notes><![CDATA[
From SpringBoot bom dependency
]]></notes>
<gav>com.jayway.jsonpath:json-path:2.8.0</gav>
<cve>CVE-2023-51074</cve>
</suppress>
</suppressions>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
id "org.owasp.dependencycheck" version "8.2.1"
id "org.owasp.dependencycheck" version "9.0.9"
}

ext.projectVersion = '3.0.0-SNAPSHOT'
Expand Down
2 changes: 1 addition & 1 deletion symphony-bdk-bom/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repositories {

dependencies {
// import Spring Boot's BOM
api platform('org.springframework.boot:spring-boot-dependencies:3.2.1')
api platform('org.springframework.boot:spring-boot-dependencies:3.2.2')
// import Jackson's BOM
api platform('com.fasterxml.jackson:jackson-bom:2.16.0')
// import Jersey's BOM
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'bdk.java-common-conventions'
id 'org.springframework.boot' version "3.2.1"
id 'org.springframework.boot' version "3.2.2"
}

description = 'Symphony Java BDK Examples for the SpringBoot integration'
Expand Down
2 changes: 1 addition & 1 deletion symphony-bdk-examples/bdk-spring-boot-example/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'bdk.java-common-conventions'
id 'org.springframework.boot' version "3.2.1"
id 'org.springframework.boot' version "3.2.2"
}

description = 'Symphony Java BDK Examples for the SpringBoot integration'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.symphony.bdk.app.spring;

import com.symphony.bdk.app.spring.config.BdkExtAppControllerConfig;

import com.symphony.bdk.app.spring.config.BdkExtAppSecurityConfig;

import com.symphony.bdk.app.spring.config.BdkExtAppTracingFilterConfig;
import com.symphony.bdk.app.spring.config.BdkHealthIndicatorConfig;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
Expand All @@ -15,7 +14,8 @@
@Import({
BdkExtAppControllerConfig.class,
BdkExtAppSecurityConfig.class,
BdkExtAppTracingFilterConfig.class
BdkExtAppTracingFilterConfig.class,
BdkHealthIndicatorConfig.class
})
@EnableConfigurationProperties(SymphonyBdkAppProperties.class)
public class SymphonyBdkAppAutoConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,19 @@
import com.symphony.bdk.app.spring.auth.CircleOfTrustController;
import com.symphony.bdk.app.spring.auth.service.CircleOfTrustService;
import com.symphony.bdk.app.spring.exception.GlobalControllerExceptionHandler;
import com.symphony.bdk.app.spring.service.SymphonyBdkHealthIndicator;
import com.symphony.bdk.core.auth.ExtensionAppAuthenticator;
import com.symphony.bdk.core.service.health.HealthService;
import com.symphony.bdk.spring.SymphonyBdkCoreProperties;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;

/**
* Configuration and injection of the main rest controllers for extension app APIs as beans within the Spring application context.
*/
public class BdkExtAppControllerConfig {

@Bean
@ConditionalOnProperty("bdk.bot.username")
@ConditionalOnMissingBean
public SymphonyBdkHealthIndicator symphonyBdkHealthIndicator(HealthService healthService) {
return new SymphonyBdkHealthIndicator(healthService);
}
@ConditionalOnProperty(name = "bdk-app.auth.enabled", havingValue = "true")
public class BdkExtAppControllerConfig {

@Bean
@ConditionalOnMissingBean
Expand All @@ -34,7 +26,7 @@ public CircleOfTrustService circleOfTrustService(ExtensionAppAuthenticator authe
}

@Bean
@ConditionalOnProperty(name = "bdk-app.auth.enabled", havingValue = "true")
@ConditionalOnMissingBean
public CircleOfTrustController circleOfTrustController(
SymphonyBdkAppProperties properties,
CircleOfTrustService circleOfTrustService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
Expand All @@ -17,6 +18,7 @@
*/
@Slf4j
@RequiredArgsConstructor
@ConditionalOnProperty(name = "bdk-app.auth.enabled", havingValue = "true")
public class BdkExtAppSecurityConfig {
private final SymphonyBdkAppProperties properties;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.symphony.bdk.app.spring.config;

import com.symphony.bdk.app.spring.service.SymphonyBdkHealthIndicator;
import com.symphony.bdk.app.spring.service.SymphonyBdkHealthIndicator.CustomStatusCodeMapper;
import com.symphony.bdk.core.service.health.HealthService;

import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;


@ConditionalOnProperty("bdk.bot.username")
public class BdkHealthIndicatorConfig {

@Bean(name = "bot")
@ConditionalOnMissingBean
public SymphonyBdkHealthIndicator symphonyBdkHealthIndicator(HealthService healthService) {
return new SymphonyBdkHealthIndicator(healthService);
}

@Bean
@ConditionalOnBean(name = "bot")
public HttpCodeStatusMapper customStatusCodeMapper() {
return new CustomStatusCodeMapper();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.apiguardian.api.API;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
import org.springframework.boot.actuate.health.Status;

import java.util.Map;
Expand Down Expand Up @@ -49,8 +50,7 @@ protected void doHealthCheck(Health.Builder builder) throws Exception {
V3Health health = healthService.healthCheckExtended();
buildHealthDetail(builder, health);
} catch (ApiRuntimeException e) {
log.debug("Health check failed, trying to parse the failure response body.", e);
log.trace("Health check failure response body - {}", e.getResponseBody());
log.warn("Health check response with exception, try parse the response entity - [{}]", e.getMessage());
try {
V3Health health = MAPPER.readValue(e.getResponseBody(), V3Health.class);
buildHealthDetail(builder, health);
Expand Down Expand Up @@ -91,4 +91,35 @@ private void buildHealthDownDetail(Health.Builder builder) {
.withDetail(CE, DOWN)
.withDetail(DFL, DOWN);
}


/**
* A custom spring actuator health endpoint status code mapper.
*
* It will return 500 for all status except Status.UP
*/
@API(status = API.Status.INTERNAL)
public static class CustomStatusCodeMapper implements HttpCodeStatusMapper {

@Override
public int getStatusCode(Status status) {
if (status == Status.DOWN) {
return 500;
}

if (status == Status.OUT_OF_SERVICE) {
return 503;
}

if (status == Status.UNKNOWN) {
return 500;
}

if (status.getCode().equals(WARNING)) {
return 500;
}

return 200;
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.symphony.bdk.app.spring.SymphonyBdkAppAutoConfiguration
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
package com.symphony.bdk.app.spring.config;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;

import com.symphony.bdk.app.spring.SymphonyBdkAppProperties;
import com.symphony.bdk.app.spring.auth.service.CircleOfTrustService;
import com.symphony.bdk.core.service.health.HealthService;

import org.junit.jupiter.api.Test;

public class BdkExtAppControllerConfigTest {

@Test
void createSymphonyBdkHealthIndicatorTest() {
final BdkExtAppControllerConfig config = new BdkExtAppControllerConfig();
final HealthService healthService = mock(HealthService.class);
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;

assertNotNull(config.symphonyBdkHealthIndicator(healthService));
}
public class BdkExtAppControllerConfigTest {

@Test
void createCircleOfTrustControllerTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class BdkExtAppSecurityConfigTest {
void corsFilters() {
final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues(
"bdk-app.auth.enabled=true",
"bdk-app.cors.[/**].allowed-origins=*",
"bdk-app.cors.[/**].allow-credentials=false",
"bdk-app.cors.[/**].allowed-methods=POST,GET",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.symphony.bdk.app.spring.config;

import com.symphony.bdk.core.service.health.HealthService;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;

class BdkHealthIndicatorConfigTest {

@Test
void createSymphonyBdkHealthIndicatorTest() {
final BdkHealthIndicatorConfig config = new BdkHealthIndicatorConfig();
final HealthService healthService = mock(HealthService.class);

assertNotNull(config.symphonyBdkHealthIndicator(healthService));

assertNotNull(config.customStatusCodeMapper());
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
package com.symphony.bdk.app.spring.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;

import com.symphony.bdk.app.spring.service.SymphonyBdkHealthIndicator.CustomStatusCodeMapper;
import com.symphony.bdk.core.service.health.HealthService;
import com.symphony.bdk.gen.api.model.V3Health;
import com.symphony.bdk.gen.api.model.V3HealthComponent;
import com.symphony.bdk.gen.api.model.V3HealthStatus;
import com.symphony.bdk.http.api.ApiException;
import com.symphony.bdk.http.api.ApiRuntimeException;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
import org.springframework.boot.actuate.health.Status;

import java.util.Collections;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class SymphonyBdkHealthIndicatorTest {
Expand Down Expand Up @@ -59,34 +68,15 @@ void doHealthCheck_withCEDown_up() throws Exception {

@Test
void doHealthCheck_exception() throws Exception {
final String body = "{\n"
+ " \"status\": \"UP\",\n"
+ " \"version\": \"2.57.0\",\n"
+ " \"services\": {\n"
+ " \"pod\": {\n"
+ " \"status\": \"UP\",\n"
+ " \"version\": \"1.57.0\"\n"
+ " },\n"
+ " \"datafeed\": {\n"
+ " \"status\": \"UP\",\n"
+ " \"version\": \"2.1.28\"\n"
+ " },\n"
+ " \"key_manager\": {\n"
+ " \"status\": \"UP\",\n"
+ " \"version\": \"1.56.0\"\n"
+ " }\n"
+ " },\n"
+ " \"users\": {\n"
+ " \"agentservice\": {\n"
+ " \"status\": \"DOWN\"\n"
+ " },\n"
+ " \"ceservice\": {\n"
+ " \"status\": \"DOWN\",\n"
+ " \"message\": \"Ceservice authentication credentials missing or misconfigured\"\n"
+ " }\n"
+ " }\n"
+ "}";

final String body =
"{\n" + " \"status\": \"UP\",\n" + " \"version\": \"2.57.0\",\n" + " \"services\": {\n" + " \"pod\": {\n"
+ " \"status\": \"UP\",\n" + " \"version\": \"1.57.0\"\n" + " },\n" + " \"datafeed\": {\n"
+ " \"status\": \"UP\",\n" + " \"version\": \"2.1.28\"\n" + " },\n"
+ " \"key_manager\": {\n" + " \"status\": \"UP\",\n" + " \"version\": \"1.56.0\"\n" + " }\n"
+ " },\n" + " \"users\": {\n" + " \"agentservice\": {\n" + " \"status\": \"DOWN\"\n" + " },\n"
+ " \"ceservice\": {\n" + " \"status\": \"DOWN\",\n"
+ " \"message\": \"Ceservice authentication credentials missing or misconfigured\"\n" + " }\n"
+ " }\n" + "}";

doThrow(new ApiRuntimeException(new ApiException(503, "message", Collections.EMPTY_MAP, body))).when(healthService)
.healthCheckExtended();
Expand All @@ -99,13 +89,8 @@ void doHealthCheck_exception() throws Exception {

@Test
void doHealthCheck_badGw_exception() throws Exception {
final String body = "<html>\n"
+ "<head><title>502 Bad Gateway</title></head>\n"
+ "<body>\n"
+ "<center><h1>502 Bad Gateway</h1></center>\n"
+ "</body>\n"
+ "</html>";

final String body = "<html>\n" + "<head><title>502 Bad Gateway</title></head>\n" + "<body>\n"
+ "<center><h1>502 Bad Gateway</h1></center>\n" + "</body>\n" + "</html>";

doThrow(new ApiRuntimeException(new ApiException(502, "message", Collections.EMPTY_MAP, body))).when(healthService)
.healthCheckExtended();
Expand All @@ -114,4 +99,25 @@ void doHealthCheck_badGw_exception() throws Exception {
Health build = builder.build();
assertThat(build.getStatus().getCode()).isEqualTo("DOWN");
}

@Nested
class CustomStatusCodeMapperTest {

HttpCodeStatusMapper mapper = new CustomStatusCodeMapper();

@ParameterizedTest
@MethodSource("getStatusArguments")
void getStatusCode_status_code(Status status, int code) {
assertThat(mapper.getStatusCode(status)).isEqualTo(code);
}

private static Stream<Arguments> getStatusArguments() {
return Stream.of(
Arguments.of(Status.UP, 200),
Arguments.of(Status.DOWN, 500),
Arguments.of(new Status("WARNING"), 500),
Arguments.of(Status.OUT_OF_SERVICE, 503),
Arguments.of(Status.UNKNOWN, 500));
}
}
}
Loading

0 comments on commit 21e93c4

Please sign in to comment.