은근 프로젝트를 하고나면 놓치기 쉬운게 종속성 관리입니다.
하나의 프로젝트에 정말 수십 수백개의 의존성이 있습니다. 이것을 모두 관리하기란 쉽지 않습니다.
우리가 자주 접하는 spring-boot만 해도 매 업데이트마다 의존성 업데이트가 있습니다.
물론 규모가 엄청 커서 그럴수도 있지만 여러분의 프로젝트도 규모가 커질수록 다양한 기능이 추가될수록 더 많은 의존성을 추가하게 될 것이고 점점 관리해야할 패키지들이 많아질 겁니다.
새로운 기능을 사용하기위해 종속성을 업데이트 할 수 있지만 그것 보다 더 중효한 것은 치명적인 에러 그로인한 보안적인 이유가 발생했을 때 패치된 버전을 빠르게 올려줘야합니다.
하지만 모든 종속성을 트레킹하며 어떤 중대한 오류가 있었는지를 확인하기는 어렵습니다.
문제점을 확인하는데 여러가지 도구가 있겠지만 저희는 인텔리제이의 플러그인 Package Search 를 사용하고 있습니다.
package Search를 사용하면 IDE 내에서 종속성을 검색, 평가 및 관리 할 수 있습니다.
(Maven, Gradle, sbt와 같은 주요 빌드 도구에서 지원됩니다)
설치하시면 아래와 같이 왼쪽바에 생성이 됩니다.
그럼 아래처럼 업데이트 할 수 있는 패키지는 오른쪽에 update 버튼이 생성됩니다.
물론 저희는 버튼이 나올 때 하는게 아니라 문제가 발생했을 때만 하고 있습니다.
예를 들어 보안상 에러가 있다면 아래와 같이 알려줍니다.
에러내용은 아래와 같습니다.
- 취약성 ID: CVE-2023-2976
- 심각도 점수: 7.1
- Google Guava의 FileBackedOutputStream에서 Java의 기본 임시 디렉터리를 사용하여 파일을 생성할 때 발생하는 취약성입니다.
- Guava 버전 1.0부터 31.1-jre까지의 버전과 Android Ice Cream Sandwich에서 발생하며, 기본 임시 디렉터리에 대한 접근 권한이 있는 사용자와 애플리케이션이 클래스에서 생성한 파일에 접근할 수 있습니다.
- 이 보안 취약성은 버전 32.0.0에서 수정되었으나, 버전 32.0.0은 Windows에서 일부 기능이 제대로 작동하지 않을 수 있습니다.
쉽게 설명하면 google-api-client:2.0.0에서 사용하는 종속성 패키지에 문제가 있다는겁니다. 따라서 2.0.0이아니라 문제가 있는 종송속 버전을 업데이트한 버전으로 업데이트하면 됩니다.
google-api-client의 github로 가보시면 2.4.0버전에서 업데이트를 했다는 것을 알 수 있습니다.
따라서 우리는 2.4.0이상으로 업데이트 하면됩니다.
현재 시점으로 마이너패치가된 최신 버전이 2.6.0이기 때문에 해당버전으로 업데이트 해도 무리가 없습니다.
따라서 바로 업데이트 버튼을 눌러주면 됩니다.
하지만 업데이트 버튼만 누르면 build.gradle만 수정되기에 Gradle reload를 해줍니다.
❗️하지만 여기서 문제가 생깁니다.
spring-boot로로 프로젝트를 하면 버전을 명시적으로 표기하지 않는 경우도 있습니다.
왜냐하면 이미 BOM에 명시되어있기 때문이죠 이미 spring-boot bom에 스프링과 호환되는 버전이 무엇인지 저장해놓았기 때문에 우리가 강제하지 않는 한 BOM에 명시되어있는 버전은 다운받게 됩니다.
Spring-boot BOM : https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-dependencies/build.gradle
❓ BOM
Bill of Materials
BOM (Bill of Materials) 개요
BOM(Bill of Materials)은 소프트웨어 프로젝트에서 사용되는 모든 구성 요소, 라이브러리, 의존성을 나열한 목록입니다. 이는 프로젝트 내에서 일관성과 호환성을 보장하기 위해 사용됩니다.
BOM의 목적
- 의존성 관리: BOM은 프로젝트에서 사용되는 의존성의 버전을 관리하여 모든 구성 요소가 서로 호환되도록 합니다.
- 일관성: 특정 버전의 의존성을 정의함으로써 모든 빌드에서 동일한 버전을 사용하게 되어 "내 컴퓨터에서는 작동하는데" 문제를 방지할 수 있습니다.
- 단순화: 개발자가 각 의존성의 버전을 개별적으로 지정할 필요 없이, BOM을 통해 중앙에서 관리할 수 있습니다.
BOM의 작동 원리
Java와 Spring Boot의 경우, BOM은 주로 특정 버전의 의존성을 명시하는 Maven POM 파일입니다. 프로젝트는 이 BOM을 가져와 개별 의존성의 버전을 지정하지 않고도 사용할 수 있습니다.
BOM의 장점
- 충돌 해결: BOM은 서로 다른 의존성 버전 간의 충돌을 피하는 데 도움이 됩니다.
- 업데이트 용이성: 단일 BOM 버전을 업데이트하면 여러 의존성을 한 번에 업그레이드할 수 있습니다.
- 중앙 관리: 버전을 중앙에서 관리하여 유지보수 및 감사가 용이합니다.
Spring Boot와 BOM
Spring Boot는 자체 BOM(spring-boot-dependencies)을 제공하여, Spring 애플리케이션에서 일반적으로 사용되는 의존성의 버전을 포함하고 있습니다. 이를 통해 모든 Spring Boot 스타터와 다른 의존성이 서로 호환되도록 보장합니다.
https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-dependencies/build.gradle
Maven에서 BOM을 사용하는 방법
BOM을 사용하려면 dependencyManagement 섹션을 활용합니다. 여기서 BOM을 가져오고, 프로젝트의 의존성 버전을 관리할 수 있습니다.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
위와 같이 dependencyManagement 섹션에 BOM을 추가합니다. 여기서 spring-boot-dependencies BOM을 가져와 Spring Boot에서 사용하는 모든 의존성의 버전을 관리합니다.
2. 의존성 선언
이제 의존성을 선언할 때는 버전을 명시하지 않아도 됩니다. Maven은 dependencyManagement 섹션에서 정의한 BOM을 참조하여 적절한 버전을 자동으로 선택합니다.
단 Maven의 경우 의존성 버전을 명시하지 않으면, 빌드 실패가 발생합니다.
Maven은 모든 의존성에 대해 명시적인 버전이 필요합니다.
따라서 여러분들이 강제로 특정 버전을 다운받는다고 해도 그 하위 의존성들도 같이 버전을 설정해주지 않는 이상 BOM에 저장되어있는 버전으로 다운받아집니다.
예를 들어봅시다.
nimbus-jose-jwt 패키지는 9.37.2 미만 버전을 사용하면 보안상 리스크가 존재합니다. (참고 : https://github.com/advisories/GHSA-gvpg-vgmx-xg6w)
따라서 9.37.2 이상의 버전으로 업그레이드 해야합니다. 우리가 직접해도 임의로 해당 패키지만 업그레이드 해도 되지만 그렇게 했을시 어떤 사이드이펙트가 생길지 아무도 모릅니다.
그렇다고 boot-starter-oauth2-client를 최신버전으로 업그레이드해도 여전히 문제는 해결되지 않습니다
현재 시점으로 최신버전이 3.3.2를 강제로 업그레이드 해도 에러가 발생하는 것을 알 수 있습니다.
왜그럴까요?
왜냐하면 boot-starter-oauth2-client 가 사용하는 패키지인 spring-security-oauth2-client는 우리가 강제로 버전을 지정하지 않았기 때문에 스프링 부트에 등록된 BOM에 맞는 버전으로 사용되기 때문이죠
실제로 의존성을보면 boot-starter-oauth2-client:3.3.2버전은 spring-security-oauth2-client:6.3.1 버전을 사용하고 있는데 스프링부트 BOM 때문에 6.2.4버전을 사용하고 있는겁니다.
이를 해결하려면 boot-starter-oauth2-client 패키지의 버전을 업데이트한 스프링부트 버전을 업그레이드 해야합니다.
현재 저희 프로젝트는 3.2.5 버전을 사용하고 있기 때문에 이 버전이상에서 boot-starter-oauth2-client 패키지의 버전을 업그레드한 버전을 찾으면 됩니다.
그래서 실제로 보면 v3.2.7에서 업그레드한 것을 알 수 있습니다.
springSecurity 6.2.5이상 버전을 사용하면 위에서 발생한 보안 경고가 사라집니다.
(아래 링크로 가보면 문제관련 이슈를 볼 수 있음)
https://github.com/spring-projects/spring-security/issues/14836
아래 링크는 oauth2-oidc-sdk에서 해당에러 때문에 pr한 사항들
https://github.com/AzureAD/microsoft-authentication-library-for-java/pull/781
https://github.com/AzureAD/microsoft-authentication-library-for-java/issues/779
그래서 업데이트 하고나면 해당 에러가 해결되었음
📚 Reference
- Maven - Dependency Mechanism
- https://spring.io/blog/2024/05/24/sbom-support-in-spring-boot-3-3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.7
- https://github.com/AzureAD/microsoft-authentication-library-for-java/pull/781
- https://github.com/AzureAD/microsoft-authentication-library-for-java/issues/779
- https://github.com/advisories/GHSA-gvpg-vgmx-xg6w
- spring-boot-starter-oauth2-client/build.gradle
'서비스 운영 일지 > Attraction' 카테고리의 다른 글
[어트랙션][ERROR] Query DSL에서 LocalDate가 이상하다? (0) | 2024.07.08 |
---|