HTTPS 内部 Maven 镜像,并让 JVM 信任
한국어 원문으로 표시합니다.
목표
연결된 쪽에서 의존성과 플러그인을 모아 사내 Maven 저장소를 HTTPS 로 세우고, settings.xml 의 mirror 로 모든 요청을 돌린다. JVM 이 사설 CA 를 믿게 해 폐쇄망 쪽 새 로컬 저장소로 빌드하고, 반입 목록에서 빠진 플러그인을 추가 반입하는 절차까지 끝낸다.
왜 중요한가
자바 빌드의 폐쇄망 실패는 세 겹이다 — 저장소 주소, 인증서, 그리고 반입 목록의 구멍. 주소는 mirror 한 줄이, 인증서는 JVM 신뢰 저장소가, 구멍은 "실제로 칠 goal 로 목록을 만든다" 는 습관이 막는다. 이 파드는 인터넷(80/443)에 닿으므로 받는 쪽 역할을 하고, 폐쇄망 쪽은 mirrorOf * 가 모든 요청을 사내 저장소로 돌려 바깥을 쓰지 못하게 한다. 채점기는 로컬 저장소의 _remote.repositories 와 사내 서버의 접근 기록으로 어디서 받았는지 확인한다.
단계
/root/mvn/app에pom.xml(gson 2.11.0, 플러그인 버전 고정)과src/main/java/demo/App.java를 만들고, 새 로컬 저장소/root/mvn/outside-repo로package를 돌린다./root/mvn/outside-repo를/srv/maven으로 옮기되_remote.repositories·*.lastUpdated·resolver-status.properties는 걷어 낸다./root/pki에 CNAirgap Internal Root CA인 루트(ca.crt·ca.key)와maven.airgap.internal서버 인증서(maven.crt·maven.key, SAN)를 만들고/etc/hosts에 이름을 더한다./root/mvn/nginx.conf로 nginx 를 띄워https://maven.airgap.internal:8443/가/srv/maven을 내주게 한다. 접근 기록은/root/mvn/access.log.~/.m2/settings.xml에 idairgap-internal, mirrorOf*인 mirror 를 적는다. 연결된 쪽 역할을 할 때 쓸 빈 설정/root/mvn/outside-settings.xml도 만든다.- 폐쇄망 쪽 새 로컬 저장소
/root/mvn/inside-repo로package를 돌려 실패하는 출력을/root/mvn/pkix.log에 저장한다. - JVM 이 사설 루트를 믿게 한다(검증을 끄는 옵션은 쓰지 않는다).
- 같은 명령으로 폐쇄망 쪽 빌드를 통과시킨다.
mvn clean package가 실패하는 원인이 된 산출물 좌표를/root/mvn/missing.txt에 적고(groupId:artifactId:version), 연결된 쪽에서 받아 사내 저장소에 더한 뒤 폐쇄망 쪽에서clean package를 통과시킨다.
참고
- 로컬 저장소 지정:
-Dmaven.repo.local=<경로>· 다른 설정 파일:-s <파일> - 어디서 받았나:
<로컬 저장소>/com/google/code/gson/gson/2.11.0/_remote.repositories - nginx 설정 검사와 기동:
nginx -t -c /root/mvn/nginx.conf→nginx -c /root/mvn/nginx.conf - JVM 저장소 보기:
keytool -list -cacerts -storepass changeit | head - 흔한 실수 1: 5단계 뒤에 연결된 쪽 명령을 그냥 치기. 사용자 settings.xml 의 mirror 가 바깥 요청까지 사내로 보냅니다 — 바깥 역할에는
-s /root/mvn/outside-settings.xml. - 흔한 실수 2: 추가 반입 뒤 바로 다시 빌드하기. 404 가 로컬 저장소에 기록되어 있어
-U가 필요합니다. - 흔한 실수 3: 첫 빌드를 이 이미지의 기본 로컬 저장소(
/root/.m2/repository)로 하기. 이미 채워진 저장소라 반입 목록이 틀어집니다.
받는 쪽: 새 로컬 저장소로 빌드해 모으기
/root/mvn/app 에 pom.xml 과 App.java 를 만들고 새 로컬 저장소 /root/mvn/outside-repo 로 package 를 돌린다.
로컬 저장소 위치를 시스템 속성으로 바꿀 수 있습니다. 새 디렉터리를 주면 이 빌드가 실제로 받은 것만 쌓입니다. 플러그인 버전을 POM 에 고정하지 않으면 이 Maven 의 기본 compiler 가 JDK 21 설정을 모릅니다.
추적 파일을 걷어 사내 저장소로
/root/mvn/outside-repo 를 /srv/maven 으로 옮기되 추적 파일(_remote.repositories·*.lastUpdated·resolver-status.properties)은 걷어 낸다.
사내 저장소는 파일 배치 그대로면 됩니다. 추적 파일은 받은 쪽 로컬 저장소가 '어디서 받았나' 를 적은 기록이라 저장소에 남으면 안 됩니다. find 로 이름을 골라 지울 수 있습니다.
사설 CA 로 미러 인증서 발급
/root/pki 에 루트(ca.crt·ca.key, CN Airgap Internal Root CA)와 maven.airgap.internal 인증서(maven.crt·maven.key, SAN)를 만들고 /etc/hosts 에 이름을 더한다.
루트는 자기 서명에 CA:TRUE, 서버 인증서는 루트로 서명하면서 확장 파일로 SAN 을 줍니다. 사설 CA 모듈에서 한 것과 같은 절차입니다.
nginx 로 HTTPS 사내 저장소 띄우기
/root/mvn/nginx.conf 로 nginx 를 띄워 https://maven.airgap.internal:8443/ 가 /srv/maven 을 내주게 하고, 접근 기록을 /root/mvn/access.log 에 남긴다.
Maven 저장소는 정적 파일이라 root 하나로 충분합니다. 이 파드에서는 1024 아래 포트를 열 수 없고, pid·로그 경로는 쓸 수 있는 곳으로 옮겨야 합니다. -t 로 먼저 검사하세요.
mirrorOf * 로 모든 요청 돌리기
~/.m2/settings.xml 에 id airgap-internal, mirrorOf *, url https://maven.airgap.internal:8443/ 인 mirror 를 적고, 빈 설정 /root/mvn/outside-settings.xml 을 만든다.
사용자 설정 파일은 홈 디렉터리의 .m2 아래에 있습니다. mirrorOf 에 별표를 주면 POM 이 선언한 저장소까지 모두 가로챕니다. 바깥 역할에 쓸 설정은 mirror 가 없는 최소한의 settings 요소면 됩니다.
JVM 이 모르는 CA — PKIX 오류 기록
새 로컬 저장소 /root/mvn/inside-repo 로 package 를 돌려 실패하는 출력을 /root/mvn/pkix.log 에 저장한다.
curl 에 루트를 알려 준 것과 JVM 이 루트를 믿는 것은 별개입니다. 실패하는 출력 전체를 저장하고, 오류 줄에서 인증서 경로에 관한 말을 찾아보세요.
JVM 신뢰 저장소에 루트 넣기
JVM 이 사설 루트를 믿게 한다(검증을 끄는 옵션은 쓰지 않는다).
JDK 에는 신뢰 저장소를 다루는 도구가 있고, 기본 저장소(cacerts)를 바로 가리키는 옵션이 있습니다. 문서가 적은 초기 비밀번호가 있습니다. 우분투라면 운영체제 저장소 갱신이 JVM 저장소까지 갱신하는 길도 있습니다.
폐쇄망 쪽 빌드 통과
6단계와 같은 명령(/root/mvn/inside-repo, package)으로 빌드를 통과시킨다.
JVM 이 루트를 믿게 된 뒤라면 같은 명령이 통과해야 합니다. 통과한 뒤 폐쇄망 쪽 로컬 저장소의 추적 파일이 어느 저장소 id 를 적었는지 보세요.
clean 한 단어가 부른 추가 반입
mvn clean package 실패의 원인 좌표를 /root/mvn/missing.txt 에 groupId:artifactId:version 으로 적고, 연결된 쪽에서 받아 사내 저장소에 더한 뒤 폐쇄망 쪽에서 clean package 를 통과시킨다.
오류 줄이 어떤 플러그인을 찾지 못했는지 알려 줍니다. 바깥 역할은 빈 설정 파일과 바깥용 로컬 저장소로 같은 goal 을 돌리면 그 플러그인이 모입니다. 다시 옮긴 뒤에도 실패한다면 오류 문장을 끝까지 읽어 보세요 — 이전 실패가 기록되어 있습니다.