diff --git a/build.gradle b/build.gradle index dc62c3b..dce87b1 100644 --- a/build.gradle +++ b/build.gradle @@ -72,9 +72,13 @@ tasks.named('check') { group = 'io.shinhanlife.dap.biz.mcp' version = '0.1.0' +// 표준가이드가 정한 배포판은 Eclipse Temurin(openjdk21u-jdk_..._hotspot_21.0.5)이다. +// 벤더를 적지 않으면 설치된 아무 JDK나 잡히므로, 가이드와 다른 배포판으로 조용히 빌드되는 것을 막는다. +// 폐쇄망에서는 toolchain 자동 다운로드가 동작하지 않으므로 빌드 머신에 Temurin이 미리 설치되어 있어야 한다. java { toolchain { languageVersion = JavaLanguageVersion.of(21) + vendor = JvmVendorSpec.ADOPTIUM } } diff --git a/docs/sbom/AXHUB_MCP_Server_SBOM_CycloneDX1.5.xlsx b/docs/sbom/AXHUB_MCP_Server_SBOM_CycloneDX1.5.xlsx deleted file mode 100644 index c38b6e0..0000000 Binary files a/docs/sbom/AXHUB_MCP_Server_SBOM_CycloneDX1.5.xlsx and /dev/null differ diff --git a/docs/sbom/AXHUB_MCP_Server_SBOM_CycloneDX1.5.json b/docs/sbom/AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json similarity index 97% rename from docs/sbom/AXHUB_MCP_Server_SBOM_CycloneDX1.5.json rename to docs/sbom/AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json index e4444dc..172949e 100644 --- a/docs/sbom/AXHUB_MCP_Server_SBOM_CycloneDX1.5.json +++ b/docs/sbom/AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json @@ -11,13 +11,13 @@ "group": "io.shinhanlife.dap.biz.mcp", "name": "ax-hub-mcp-server", "version": "0.1.0", - "description": "AX HUB MCP Server (Spring Boot 3.5.11 / Java 21)", + "description": "AXHUB MCP&Tool Service 공통 스택 (Java 21 / Spring Boot 3.5.11)", "purl": "pkg:maven/io.shinhanlife.dap.biz.mcp/ax-hub-mcp-server@0.1.0" }, "properties": [ { "name": "axhub:scope", - "value": "MCP Java SDK 2.0.0과 그 런타임 전이 의존, 그리고 빌드 환경" + "value": "MCP Java SDK 2.0.0과 그 런타임 전이 의존, 그리고 빌드 환경. MCP Server와 Tool Service의 공통 스택에 적용된다" }, { "name": "axhub:source", @@ -153,7 +153,7 @@ }, { "name": "axhub:note", - "value": "문서 밖 $ref 조회는 ToolSchemaReferencePolicy가 차단(ADR-0011). joni·graal-js 미해석으로 pattern 검증이 java.util.regex(백트래킹)로 처리되어, ToolSchemaPatternPolicy가 반복 구조·수량자 개수·maxLength를 제한하고 patternProperties를 금지한다(ADR-0012). 둘 다 ToolMetadata 생성 시점 검사" + "value": "optional인 joni·graal-js를 해석하지 않아 pattern 검증에 JDK 정규식 엔진을 사용한다" } ] }, diff --git a/docs/sbom/AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx b/docs/sbom/AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx new file mode 100644 index 0000000..0b7d7a6 Binary files /dev/null and b/docs/sbom/AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx differ diff --git a/docs/sbom/README.md b/docs/sbom/README.md index b09e16c..ba1cf46 100644 --- a/docs/sbom/README.md +++ b/docs/sbom/README.md @@ -1,15 +1,21 @@ -# SBOM — AX HUB MCP Server +# SBOM — AXHUB MCP&Tool Service -- 산출물: `AXHUB_MCP_Server_SBOM_CycloneDX1.5.json` (CycloneDX 1.5 정본), `AXHUB_MCP_Server_SBOM_CycloneDX1.5.xlsx` (검토용) -- 대상: `ax-hub-mcp-server@0.1.0` (Java 21 / Spring Boot 3.5.11) +- 산출물: `AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json` (CycloneDX 1.5 정본), `AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx` (검토용) +- 대상: AXHUB MCP Server와 Tool Service의 공통 스택 (Java 21 / Spring Boot 3.5.11) +- 산출 기준 빌드: `ax-hub-mcp-server@0.1.0` - 생성 기준일: 2026-08-18 ## 대상 범위 +MCP Server와 Tool Service는 같은 기술 스택과 같은 MCP SDK를 쓰므로 이 SBOM을 공통으로 적용한다. `build.gradle`이 직접 선언한 오픈소스는 `io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0` 하나이며, 이 SBOM은 그 **런타임 전이 의존 전체**와 **빌드 환경**을 담는다. Spring Boot starter 계열(web / validation / data-redis / actuator)은 glow f/w가 제공하는 플랫폼 구성이라 범위 밖이다. +다만 목록은 **MCP Server 빌드(`ax-hub-mcp-server@0.1.0`) 하나에서 산출했다.** Tool Service가 이 +스택 밖의 의존(예: DB 드라이버, 연계 라이브러리)을 추가하면 그만큼은 이 SBOM에 없으므로, 해당 +빌드에서 다시 산출해 합쳐야 한다. + | 구분 | 개수 | 내용 | |---|---|---| | 런타임 의존성 (scope: required) | 12 | 실행 산출물 classpath에 올라가는 라이브러리 | @@ -20,45 +26,20 @@ 공개 의무가 없다. JDK는 toolchain이 `languageVersion = 21`만 고정하고 벤더를 지정하지 않으므로, 실제 배포판이 정해지면 라이선스를 확정해 기재한다. -## 빌드 환경(scope: optional)과 제외 devDependencies의 차이 +## 제외 항목 -둘은 다르다. 혼동하지 않도록 구분해 둔다. +제외 항목과 사유는 엑셀 `Exclusions` 시트가 정본이다. 요약하면 다음과 같다. -- **빌드 환경 (scope: optional)** — BOM에 **수록한다**. JDK 21, Gradle 8.14.3처럼 빌드에 필요하지만 - 실행 산출물에는 들어가지 않는 것들이다. -- **제외 devDependencies** — BOM에 **수록하지 않는다**. Java에서는 `test` scope와 - `annotationProcessor`가 여기 해당한다. 선언 4건이다. +- **test scope와 annotationProcessor** — 선언 4건. 산출물에 포함되지 않는다. - `spring-boot-starter-test`, `com.squareup.okhttp3:mockwebserver:4.12.0`, `org.junit.platform:junit-platform-launcher` (test scope) - `org.springframework.boot:spring-boot-configuration-processor` (annotationProcessor) - -나머지 제외 항목과 사유는 엑셀 `Exclusions` 시트에 있다. 핵심은 세 가지다. - - `joni`, `graal-js`, `graal-sdk` — json-schema-validator의 `optional`. ECMA262 정규식 검증을 쓰지 않아 해석되지 않으므로 약 50MB가 빠진다. - `jakarta.servlet-api:6.1.0` — mcp-core의 `provided`. 산출물에 포함되지 않고 서블릿 컨테이너가 제공한다. - `mcp:2.0.0`(aggregate), `mcp-json-jackson3:2.0.0` — Jackson 3 경로를 쓰지 않아 선언하지 않는다. 자세한 배경은 [mcp-java-sdk-adoption.md](../mcp-java-sdk-adoption.md) 참고. -## 적용된 보안 통제 - -`com.networknt:json-schema-validator`는 schema의 `$ref`가 문서 밖을 가리키면 그 주소로 직접 조회를 -시도한다. `inputSchema`는 Tool Service 매니페스트에서 오므로, 통제가 없으면 매니페스트가 서버의 -outbound 호출 대상을 정하게 된다. - -`ToolSchemaReferencePolicy`가 `ToolMetadata` 생성 시점에 문서 밖 `$ref`·`$dynamicRef`와 2020-12가 아닌 -`$schema`를 거부한다. 근거와 검토한 대안은 -[ADR-0011](../decisions/ADR-0011-tool-input-schema-stays-in-document.md)에 있다. - -정규식도 같은 자리에서 막는다. optional인 `joni`·`graal-js`를 해석하지 않아 `pattern` 검증이 JDK 정규식 -엔진으로 처리되고 백트래킹 폭증이 가능하므로, `ToolSchemaPatternPolicy`가 반복 구조와 수량자 개수, 정규식 -길이를 제한하고 `pattern` 필드에 `maxLength`(≤256) 동반 선언을 요구한다. key 길이를 묶을 자리가 없는 -`patternProperties`는 사용을 금지한다. 규칙은 JDK 21 실측에 근거하며 근거와 한계는 -[ADR-0012](../decisions/ADR-0012-tool-input-schema-pattern-budget.md)에 있다. - -남은 위험은 문자 집합이 겹치면서 무한 수량자가 3개 이하인 정규식이다. 이 조합은 통과하며 `maxLength`가 -256이면 수백 ms가 걸릴 수 있다. 두 통제는 위험을 없애지 않고 측정된 폭증 구간 밖으로 옮긴다. - ## 산출 방법과 한계 버전과 해시는 `build.gradle` 선언에서 출발해 Gradle 로컬 캐시의 실제 `pom`을 따라가 그래프를