::: IT인터넷 :::

Maven 저장소에 사용할 Nexus 서버의 자체 서명 인증서 교체

곰탱이푸우 2023. 7. 13. 08:20
 
Nexus에 Maven 저장소를 설정하고 사용하는 경우 인증서 오류가 발생하는 경우가 존재한다.
Nexus에 Maven 저장소를 설정하는 방법은 아래 포스팅을 참고한다.
인증서 오류는 대부분 자체 서명 인증서를 사용하는 경우로 한정된다.
Let's Encrypt 같은 무료 인증서를 사용하면서 오류가 발생하는 경우에도 참고한다.
 
Nexus 서버에 자체 서명 인증서를 사용하는 경우 개발환경에서 저장소 접근이 불가능한 경우가 발생한다.
특히 도메인 (URL)을 사용하는 것이 아닌 IP 주소를 URL로 사용하는 서버의 경우 사설 인증서 정보를 확인해야 한다.
 
Maven 3.0.5 버전부터 Man-In-the-Middle 공격을 방지하기 위해 인증서 검증이 필수로 적용되었다.
이로 인해 자체 서명 인증서의 경우 해당 서버에 적용 된 인증서 검증이 되지 않아 예외가 발생한다.
# 사설인증서 인증 실패
javax.net.ssl.SSLPeerUnverifiedException: Hostname 서버IP not verified

# 사설인증서의 rootca 인증서 검증 실패
javax.net.ssl.SSLHandshakeException: PKIX path validation failed:
java.security.cert.CertPathValidatorException: signature check failed

# 인증서 정보에 IP 정보 없음
Server access Error: No subject alternative names matching IP address 서버IP found
 
IP 주소를 서버 주소로 사용하면서 위와 같은 오류가 발생한 경우 Nexus의 사설 인증서를 교체해야 한다.

 

 

rootca 인증서 생성

보통 자체 서명 인증서를 생성하는 경우 상위 인증서인 rootca 인증서도 직접 생성하는 경우가 많다.
해당 인증서의 경우 기존에 사용하던 인증서를 그대로 사용해도 무방하다.
 
rootca 인증서와 서버IP주소.np.key 파일 생성 방법은 아래 문서를 참고한다.
아래 문서에도 자세하게 정리되어 있다.

서버 인증서 생성

서버에서 사용하기 위한 인증서를 생성한다.
 

conf 파일 생성

인증서 생성에 사용할 정보를 포함하는 conf 파일을 생성한다.
$ vi 서버IP주소.conf

[req]
default_bits            = 2048
default_md              = sha1
default_keyfile        = 서버IP주소.np.key
distinguished_name      = req_distinguished_name
extensions            = v3_user
## 인증서 요청시에도 extension 이 들어가면 authorityKeyIdentifier 를 찾지 못해 에러가 나므로 막아둔다.
## req_extensions = v3_user

[v3_user]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
authorityKeyIdentifier = keyid,issuer
subjectKeyIdentifier = hash
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
## SSL 용 확장키 필드
extendedKeyUsage = serverAuth,clientAuth
subjectAltName          = @alt_names
[alt_names]
IP.1 = 서버IP주소

[req_distinguished_name ]
countryName                    = Country Name (2 letter code)
countryName_default            = KR
countryName_min                = 2
countryName_max                = 2

# 회사명 입력
organizationName              = Organization Name (eg, company)
organizationName_default      = 회사명
# 부서 입력
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = 조직명
# SSL 서비스할 domain 명 입력
commonName                      = Common Name (eg, your name or your server's hostname)
commonName_default            = 서버IP주소
commonName_max                  = 64​
 
위의 코드에서 아래 항목들은 실제 사용할 값으로 수정한다.
  • 서버주소로 표기 된 부분은 사용하는 서버의 IP 주소로 변경
  • 회사명과 조직명 부분은 소속 회사 또는 임의의 이름 입력
 
[v3_user] 항목의 subjectAltName에 해당하는 [alt_names] 항목은 중요하므로 아래 내용을 반드시 확인한다.
구분
alt_names
commonName_default
IP만 사용
구분자는 IP.숫자,
값은 반드시 IP주소 지정
(ex. IP.1 = 123.45.67.89)
반드시 IP 주소 지정 (alt_names와 동일한 값)
(ex. commonName_default = 123.45.67.89)
Domain 존재
구분자는 DNS.숫자,
값은 FQDN 또는 *.DOMAIN.TLD
(ex. DNS.1 = abc.test.com  DNS.2 = *.test.com)
보통 FQDN 지정
(ex. commonName_default = abc.test.com)
 
 

서버 인증서 생성

아래 명령을 사용하여 jks 파일을 생성한다.
$ sudo openssl req -new -key 서버주소.np.key -out 서버주소.csr -config 서버주소.conf

$ sudo openssl x509 -req -days 3650 -extensions v3_user -in 서버주소.csr \
    -CA rootca.crt -CAcreateserial -CAkey rootca.key -out 서버주소.crt -extfile 서버주소.conf

$ sudo openssl x509 -in 서버주소.crt -out 서버주소.pem -outform PEM

$ sudo openssl pkcs12 -export -name 서버주소 -in 서버주소.pem \
    -inkey 서버주소.np.key -out 서버주소.pfx

$ sudo keytool -importkeystore -srckeystore 서버주소.pfx -srcstoretype pkcs12 \
    -destkeystore 서버주소.jks -deststoretype pkcs12
 
가장 마지막 항목인 keytool을 사용한 jks 파일 생성은 JDK가 설치된 환경에서 진행해야 한다.
 
기본적인 방법은 아래 문서를 참고한다.
 

서버 인증서 교체

Nexus를 Docker로 운영 중인 경우 인증서 파일을 쉽게 변경할 수 있다.
 
아래와 같이 변경한다.
# cp 서버주소.jks /NEXUS공유볼륨경로/etc/ssl 

# 아래는 예시
$ cp 123.45.67.89.jks /data/docker/nexus/nexus-data/etc/ssl

# Docker 재시작
$ docker restart nexus컨테이너이름

 

Nexus 서비스에 생성한 인증서가 실제로 적용되어야 하므로 Nexus 서버를 재시작하는 것이 상당히 중요하다.
Docker 컨테이너로 운영 중인 경우 컨테이너를 재시작한다.