[클밋] 스프링 애플리케이션에서 SSL 인증받으며 생긴 문제 - 발급과 원인

박지운·2024년 4월 10일
1

클라이밍 앱 '클밋'을 제작하며 고민/개발 내용을 기록한 글입니다.

출처 : 게비스콘 생성기

3개월 전,,,

3개월 전, 클밋 프로젝트를 진행하며 2개의 도메인에 대한 인증서를 발급받았다.

이 글을 작성하는 이유는, HTTPS 통신을 위해 발급받은 인증서와 관련해 갑자기 문제가 생겼기 때문이다. 당시 보안, 인증 과정에 대한 이해없이 단순히 블로그를 보며 따라만했고 이것이 얼마나 좋지 않은지 느꼈다.
개념부터 이해하는 과정을 정리하며 문제를 해결해보려한다.


SSL 인증서 발급

도메인은 가비아에서 구매했다.

작성하며 생각해보니 그때 굳이 도메인을 왜 2개 샀을까란 생각도 문득 들었다. 다음에는 서브 도메인을 통해 하나의 도메인에 2개의 ip를 연결하는 방식을 고민해봐야겠다.

A타입에 호스트 WWW로 ip연결 후에 잘 연결됐는지 확인했다.

이후 ec2로 접속해 certbot을 설치했다.

설치 후 나는 발급 방식 4가지 중에 standalone으로 80포트를 통해 발급하는 방식을 선택했다.
사실 선택이 아니라 블로그에서 하는 대로 따라했다.

certbot 공식문서

standalone방식을 사용했는데 이미 웹서버로 nginx를 쓰고 있었기에 nginx를 중지하며 발급받았었다. 자동으로 nginx설정을 해주는 옵션이 있었는데
공식문서를 한번이라도 읽어봤다면.....ㅎ

아무튼 발급을 진행하면

/etc/letsencrypt/live/도메인 경로에 fullchain.pem 과 privkey.prem이 발급이 되었다고 나온다.


키 변환

이제 스프링에서 사용을 해야하기에 pem.key를 .p12로 바꿔야한다.
(Java 기반 애플리케이션에서 지원하는 KeyStore Type은 JKS, JCEKS, PKCS12(p12)가 있다.)

sudo openssl pkcs12 
-export 
-in fullchain.pem 
-inkey privkey.pem 
-out keystore.p12 
-name ttp -CAfile chain.pem -caname root

명령어를 입력후 비밀번호를 설정하면 keystore.p12파일이 생성된다.
이때 비밀번호를 잘 저장해두자

스프링으로 가져오기

이제 이 인증서를 스프링 프로젝트의 resource폴더에 위치시켜야 https통신이 가능하다.
가져오기 위해 scp명령어를 사용하자.
하지만!
아까 key파일 경로에 있던 live에 있는 파일을 그대로 가져오는 것에 계속 실패했다. 그래서 방식을 로컬 -> ec2 live디렉토리에서 수정했다.
ec2 live디렉토리 -> ec2 home디렉토리 로 빼낸 후에
로컬 -> ec2 home디렉토리로 가져왔다. 중간에 home으로 빼내는 과정만 추가된 것이다.


#0. 권한 변경
sudo su로 해야 live 디렉토리 접근 가능

#1. 끄집어내
sudo cp /etc/letsencrypt/live/도메인 이름/keystore.p12 /home/ubuntu/
#2. 파일 권한을 현재 ubuntu사용자로

#3. mac터미널에서 복사
scp -i "/Users/gourderased/Folders/keys/pem키 이름" ubuntu@(ip수정):/home/ubuntu/keystore.p12 /Users/gourderased/Downloads/


스프링 설정

이제 이 인증서를 resource에 들어가도록 하면 된다.
클밋의 경우 프라이빗 서브모듈에 넣어주었다.

빌드시에 서브모듈 디렉토리에서 resource로 복사되도록해 인증서가 외부에 노출되지 않도록 했다.
인증서가 노출된 경우 공격자가 암호화된 통신을 복호화할 수 있다.

이제 스프링의 yml에 ssl 관련 설정값을 넣어주면 된다.

server:
  ssl:
  	//classpath -> default값은 resource라고 한다.
    //resource에 p12파일을 둘거면 그대로 사용하면 된다.
    key-store: classpath:keystore.p12
    key-store-password: 변환시 설정한 비밀번호
    key-store-type: PKCS12

자동 갱신 설정

이후 리눅스 스케줄러인 crontab을 통해 자동갱신설정을 해주면 된다.

# 편집기 열기
crontab -e

	매일 새벽 3시 renew를 수행해 certbot이 만료된 인증서가 있는지 확인 & 갱신
0 3 * * * /usr/bin/certbot renew --quiet

#quiet은 갱신시 별다른 로그를 남기지 않는 옵션이다.
#renew를 매일하는 것이 아닌 만료일이 임박했을 때만 수행되기 때문에 부담되지 않는다고한다.(출처 : 지피티)

그럼 이렇게 갱신해줘야하는 인증서는 만료 기한이 언제일까?

바로 3개월이다...!!
위 설정을 한 뒤 3개월 뒤인 지금 나는 인증서 만료로 서버에 api요청이 막힌 문제를 겪고 있다.


갱신도 해주었는데 왜???

처음에 인증서 만료됐다는 것을 봤을 때 의아했다. 갱신을 해주는데 왜 만료가 됐을까 궁금했다.

명령어로 인증서 기한을 확인해보니 갱신은 올바르게 이루어지고 있었다.

바로 서브 모듈에 있는 인증서가 만료가 된 것이다. 인증서 갱신은 당연히 live 디렉토리에 있는 pem키를 갱신하는 것이다.
따라서 지금과 같은 방식은 만료전에 또 스프링 프로젝트로 옮겨줘야 한다.

보통 블로그에서는 스프링에 인증서를 옮긴 후에 https접속을 확인한다.
그리고 인증서 자동 갱신 명령어를 crontab에 적어준다.

생각없이 따라만하니 인증서가 자동갱신이 되는구나 하고 넘겼던 것이다.

일단 키를 로컬로 옮긴후 또 서브모듈에 넣어준 후 빌드를 하면 당장은 해결된다.
하지만 아무리 3개월이라도 매번 옮기는 것보다는 더 좋은 방법을 찾아야한다.(오히려 3개월이면 잊어버릴 것 같다.)


이해없이 따라만하는 것은 개발 환경 설정에도 코드 작성에도 매우 위험한 습관인 것 같다.
다음 포스팅으로는 https에 대해 알아보고 위 문제를 어떻게 해결할 지에 대한 내용으로 작성할 것이다.

해결과정

profile
앞길막막 전과생

0개의 댓글