Skip to content

Commit

Permalink
APPS-941 Fix http2 rapid-reset vulnerability (#159)
Browse files Browse the repository at this point in the history
* dep: APPS-942 fix http2 rapid-reset CVE-2023-44487

* dep: Upgrade springdoc-openapi-ui to 2.2.0

* dep: Upgrade resilience4j-micrometer to 2.1.0

* dep: Upgrade to spring-aspects:6.0.13 and git-version:3.0.0
  • Loading branch information
Jesse S authored Oct 25, 2023
1 parent 8a10193 commit 2f3e05f
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 207 deletions.
20 changes: 10 additions & 10 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
buildscript {
ext {
springBootVersion = "2.7.11"
springBootVersion = "3.0.12"
httpclientVersion = "4.5.14"
aerospikeClientVersion = findProperty("aerospikeClientVersion") ?: "7.1.0"
set('snakeyaml.version', '2.0') // Can be removed after upgrading to springboot 3.x
}
if (findProperty("aerospikeUseLocal")) {
print("using Local repo")
Expand All @@ -19,9 +18,11 @@ buildscript {
}
}


plugins {
id("org.springdoc.openapi-gradle-plugin") version "1.6.0"
id 'com.palantir.git-version' version "0.15.0"
id("application")
id('com.palantir.git-version') version "3.0.0"
id("org.springdoc.openapi-gradle-plugin") version "1.8.0"
}

if (findProperty("aerospikeUseLocal")) {
Expand Down Expand Up @@ -72,21 +73,20 @@ openApi {

dependencies {
implementation('org.msgpack:msgpack-core:0.9.3')
implementation('org.springframework.boot:spring-boot-starter-web:3.0.6')
// Separately upgraded to fix vulnerability. Version should be removed after upgrading to spring-boot 3.x
implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
implementation("com.aerospike:aerospike-client:${aerospikeClientVersion}")
implementation("com.aerospike:aerospike-document-api:1.2.0")
implementation("org.msgpack:jackson-dataformat-msgpack:0.9.3")
implementation('org.springframework.retry:spring-retry:2.0.1')
implementation('org.springframework:spring-aspects:6.0.6')
implementation("org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j:2.1.7")
implementation('org.springdoc:springdoc-openapi-ui:1.6.14')
implementation('org.springframework:spring-aspects:6.0.13')
implementation('org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j:3.0.3')
implementation('org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0')
implementation("javax.inject:javax.inject:1")
implementation("com.google.guava:guava:32.1.3-jre")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.apache.httpcomponents:httpclient:${httpclientVersion}")
implementation('org.springframework.boot:spring-boot-starter-actuator')
implementation('io.github.resilience4j:resilience4j-micrometer:1.7.1')
implementation('io.github.resilience4j:resilience4j-micrometer:2.1.0')
implementation('io.micrometer:micrometer-registry-prometheus')
testImplementation("junit:junit:4.13.2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.fasterxml.jackson.databind.JsonMappingException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
Expand All @@ -41,12 +42,13 @@ public ResponseEntity<Object> handleAsError(AerospikeException ex) {
}

@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders headers, HttpStatus status,
WebRequest request) {
protected ResponseEntity<Object> handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request
) {
logger.warn(ex.getMessage());
return new ResponseEntity<>(new RestClientError(ex.getMostSpecificCause().getMessage()),
HttpStatus.BAD_REQUEST);
HttpStatus.BAD_REQUEST
);
}

@ExceptionHandler({RestClientErrors.AerospikeRestClientError.class})
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/aerospike/restclient/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
package com.aerospike.restclient.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
Expand All @@ -53,12 +54,12 @@ public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
converters.add(0, new MsgPackConverter());
converters.add(0, new JSONMessageConverter());
converters.add(0, new StringHttpMessageConverter());
converters.add(0, new ByteArrayHttpMessageConverter());
}

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*").allowedHeaders("*");
//.allowCredentials(Boolean.TRUE);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

@Tag(name = "Admin Operations", description = "Manage users and privileges.")
Expand Down Expand Up @@ -101,12 +101,12 @@ public User[] getUsers(@RequestHeader(value = "Authorization", required = false)
)
@DefaultRestClientAPIResponses
@RequestMapping(
method = RequestMethod.GET,
value = "/user/{user}",
produces = {"application/json", "application/msgpack"}
method = RequestMethod.GET, value = "/user/{user}", produces = {"application/json", "application/msgpack"}
)
public User getUser(@Parameter(required = true) @PathVariable(value = "user") String user,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public User getUser(
@Parameter(required = true) @PathVariable(value = "user") String user,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
return adminService.getUser(authDetails, user);
Expand All @@ -131,8 +131,10 @@ public User getUser(@Parameter(required = true) @PathVariable(value = "user") St
@DefaultRestClientAPIResponses
@ResponseStatus(value = HttpStatus.ACCEPTED)
@DeleteMapping(value = "/user/{user}", produces = {"application/json", "application/msgpack"})
public void dropUser(@Parameter(required = true) @PathVariable(value = "user") String user,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void dropUser(
@Parameter(required = true) @PathVariable(value = "user") String user,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.dropUser(authDetails, user);
Expand Down Expand Up @@ -161,9 +163,11 @@ public void dropUser(@Parameter(required = true) @PathVariable(value = "user") S
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void changePassword(@Parameter(required = true) @PathVariable(value = "user") String user,
@Parameter(required = true) @RequestBody String password,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void changePassword(
@Parameter(required = true) @PathVariable(value = "user") String user,
@Parameter(required = true) @RequestBody String password,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.changePassword(authDetails, user, password);
Expand Down Expand Up @@ -196,8 +200,10 @@ public void changePassword(@Parameter(required = true) @PathVariable(value = "us
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void createUser(@Parameter(required = true) @Valid @RequestBody RestClientUserModel userInfo,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void createUser(
@Parameter(required = true) @Valid @RequestBody RestClientUserModel userInfo,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.createUser(authDetails, userInfo);
Expand Down Expand Up @@ -231,17 +237,17 @@ public void createUser(@Parameter(required = true) @Valid @RequestBody RestClien
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void grantRoles(@Parameter(required = true) @PathVariable(value = "user") String user,
@io.swagger.v3.oas.annotations.parameters.RequestBody(
required = true,
content = @Content(
examples = @ExampleObject(
name = RequestBodyExamples.ROLES_NAME,
value = RequestBodyExamples.ROLES_VALUE
)
)
) @RequestBody List<String> roles,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void grantRoles(
@Parameter(required = true) @PathVariable(value = "user") String user,
@io.swagger.v3.oas.annotations.parameters.RequestBody(
required = true, content = @Content(
examples = @ExampleObject(
name = RequestBodyExamples.ROLES_NAME, value = RequestBodyExamples.ROLES_VALUE
)
)
) @RequestBody List<String> roles,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.grantRoles(authDetails, user, roles);
Expand Down Expand Up @@ -275,18 +281,17 @@ public void grantRoles(@Parameter(required = true) @PathVariable(value = "user")
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void revokeRoles(@PathVariable(value = "user") @Parameter(
description = "The user from which to revoke roles",
required = true
) String user, @io.swagger.v3.oas.annotations.parameters.RequestBody(
required = true,
content = @Content(
examples = @ExampleObject(
name = RequestBodyExamples.ROLES_NAME,
value = RequestBodyExamples.ROLES_VALUE
)
public void revokeRoles(
@PathVariable(value = "user") @Parameter(
description = "The user from which to revoke roles", required = true
) String user, @io.swagger.v3.oas.annotations.parameters.RequestBody(
required = true, content = @Content(
examples = @ExampleObject(
name = RequestBodyExamples.ROLES_NAME, value = RequestBodyExamples.ROLES_VALUE
)
) @RequestBody List<String> roles, @RequestHeader(value = "Authorization", required = false) String basicAuth) {
)
) @RequestBody List<String> roles, @RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.revokeRoles(authDetails, user, roles);
Expand Down Expand Up @@ -339,8 +344,10 @@ public List<RestClientRole> getRoles(@RequestHeader(value = "Authorization", req
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void createRole(@Parameter(required = true) @RequestBody RestClientRole rcRole,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void createRole(
@Parameter(required = true) @RequestBody RestClientRole rcRole,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.createRole(authDetails, rcRole);
Expand All @@ -364,11 +371,12 @@ public void createRole(@Parameter(required = true) @RequestBody RestClientRole r
)
@DefaultRestClientAPIResponses
@GetMapping(value = "/role/{name}", produces = {"application/json", "application/msgpack"})
public RestClientRole getRole(@Parameter(
description = "The name of the role whose information should be retrieved.",
required = true
) @PathVariable(value = "name") String role,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public RestClientRole getRole(
@Parameter(
description = "The name of the role whose information should be retrieved.", required = true
) @PathVariable(value = "name") String role,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
return adminService.getRole(authDetails, role);
Expand Down Expand Up @@ -401,11 +409,13 @@ public RestClientRole getRole(@Parameter(
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void setRoleQuotas(@Parameter(
description = "The name of the role to which quotas will be set.",
required = true
) @PathVariable(value = "name") String name, @Parameter(required = true) @RequestBody RestClientRoleQuota roleQuota,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void setRoleQuotas(
@Parameter(
description = "The name of the role to which quotas will be set.", required = true
) @PathVariable(value = "name") String name,
@Parameter(required = true) @RequestBody RestClientRoleQuota roleQuota,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.setRoleQuotas(authDetails, name, roleQuota);
Expand All @@ -430,11 +440,12 @@ public void setRoleQuotas(@Parameter(
@DefaultRestClientAPIResponses
@ResponseStatus(value = HttpStatus.ACCEPTED)
@DeleteMapping(value = "/role/{name}", produces = {"application/json", "application/msgpack"})
public void dropRole(@Parameter(
description = "The name of the role to remove.",
required = true
) @PathVariable(value = "name") String role,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void dropRole(
@Parameter(
description = "The name of the role to remove.", required = true
) @PathVariable(value = "name") String role,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.dropRole(authDetails, role);
Expand Down Expand Up @@ -467,12 +478,13 @@ public void dropRole(@Parameter(
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void grantPrivileges(@Parameter(
description = "The name of the role to which privileges will be granted.",
required = true
) @PathVariable(value = "name") String name,
@Parameter(required = true) @RequestBody List<RestClientPrivilege> privileges,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void grantPrivileges(
@Parameter(
description = "The name of the role to which privileges will be granted.", required = true
) @PathVariable(value = "name") String name,
@Parameter(required = true) @RequestBody List<RestClientPrivilege> privileges,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.grantPrivileges(authDetails, name, privileges);
Expand Down Expand Up @@ -505,12 +517,13 @@ public void grantPrivileges(@Parameter(
consumes = {"application/json", "application/msgpack"},
produces = {"application/json", "application/msgpack"}
)
public void revokePrivileges(@Parameter(
description = "The name of the role from which privileges will be removed.",
required = true
) @PathVariable(value = "name") String name,
@Parameter(required = true) @RequestBody List<RestClientPrivilege> privileges,
@RequestHeader(value = "Authorization", required = false) String basicAuth) {
public void revokePrivileges(
@Parameter(
description = "The name of the role from which privileges will be removed.", required = true
) @PathVariable(value = "name") String name,
@Parameter(required = true) @RequestBody List<RestClientPrivilege> privileges,
@RequestHeader(value = "Authorization", required = false) String basicAuth
) {

AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth);
adminService.revokePrivileges(authDetails, name, privileges);
Expand Down
Loading

0 comments on commit 2f3e05f

Please sign in to comment.