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

박지운·2024년 4월 16일
0

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

원인
HTTP와 HTTPS


해결방식

2가지의 선택지가 있다.

ssl설정을 지금처럼 톰캣에서 해주는대신 인증서를 업데이트 하는 방식과 nginx에서 해주는 방식이 있다.

ssl 설정 내장 톰캣 유지

먼저 내장 톰캣 그대로 사용하는 방법이 있다.
만약 톰캣을 쓴다면 스프링 빌드를 어떻게 할 지 결정해야한다.

왜냐하면 톰캣의 ssl인증서는 런타임에 수정이 불가하다.
빌드시에 메모리에 올라가기 때문이다.
때문에 인증서가 갱신이 되고 이를 톰캣에서도 갖고 있게 하려면 빌드를 다시 해줘야한다.

현재 스프링 빌드를 깃허브 액션에서 하기 때문에 ec2에서 갱신되는 인증서를 다시 깃허브 액션 리눅스로 가져온 후에 스프링 빌드를 다시 해줘야한다.
이후 다시 도커 이미지 빌드 후 푸시,,,등 기존 배포 과정을 인증서 갱신때문에 다시 한번 해야한다.

배포 과정

만약 이렇게 한다면 깃허브 액션 워크플로우를 스케줄로 crontab설정을 해 3개월에 한번씩 실행되게 해야한다.
뿐만 아니라 pem키가 갱신되는 것이기 때문에 인증서 갱신 후 p12변환도 매번 해줘야한다. 이 또한 쉘 스크립트로 작성 후 인증서를 갱신하는 crontab에 추가시켜줘야한다.

nginx

nginx에서는 ssl설정을 간편히 해줄 수 있다. 또한 인증서가 갱신되더라도 다시 빌드할 필요없이 ec2에서 nginx만 재시작해주면 되기 때문에 앞선 방법보다 훨씬 간편하다.

또한 포트 포워딩까지 같이 해줄 수 있기 때문에 tomcat에서 nginx로 ssl설정을 변경했다.

앞선 실수를 다시하지 않기 위해 단순히 따라하지 않고 코드마다 어떤 역할을 하는지 이해하며 작성했다.

아래 세 가지를 작성해줄 것이다.

  • ssl 인증서 설정
  • 80포트로 요청시 443포트로 포워딩
  • 443포트 요청시 8080포트로 포워딩

nginx 설정

Nginx는 구성 파일을 지정된 지시어를 통해 제어할 수 있다.
지시어는 간단한 지시어블록 지시어로 나뉜다.
전자는 세미콜론으로 후자는 {} 중괄호에 있는 지시어들을 포함한다.
만약 블록 지시어 내에 다른 지시어들이 포함된다면 컨텍스트 (http, server, location)라고 한다.

디렉토리 구조도 알아보자

알아야할 파일은 크게 3가지가 있다.

  • nginx.conf
    메인 설정 파일이다.
    연결 처리 방식, 타임아웃, 보안 설정 등등이 가능하다.
  • sites-available
    서버에서 가능한 모든 웹사이트의 구성 파일을 저장한다. 여기에 있는 파일은 Nginx에 의해 직접 참조되지 않는다.
    활성화를 위해서는 sites-enable 디렉토리에 링크를 걸어야 한다.
  • sites-enabled
    sites-available 에서 만든 설정을 sites-enabled 에서 심볼릭 링크 형태로 활성화한다.
available과 enabled를 나누는 이유는 여러 도메인을 관리하거나 
복잡한 환경을 관리할 때 사용한다고 한다.
(출처 : 지피티)
available에 작성은 모두 해두고 
enabled에서 상황에 따라 활성화/비활성화가 가능하기 때문인것같다.

따라서 available에서 설정을 해주면 된다.

만약 nginx.conf에서 수정한다면 아래 우선순위를 조심하자.

  1. server_name이 구체적으로 일치하는 경우
    (와일드 카드보다 우선순위라는 뜻)
  2. 설정 파일의 로드 순서
    server_name이 같을 경우 nginx.conf보다 sites-enabled에서 로드된 서버 블록이 우선 순위가 높다.
#etc/nginx/sites-available/
#sites-available에 있는 default파일은 주석처리

# 아래 블록을 http블록안에 추가해주면 된다.

# 80포트
server {
        listen 80;
        server_name www.testclimeet.shop;
        # 80포트를 https, 즉 443포트로 포워딩한다.
        # 301은 리소스가 이동한다는 http상태코드이다.
        # rquest_uri는 http로 요청했을때의 도메인 뒤 쿼리 스트링을 그대로 https로 전달해주는 것이다.
        return 301 https://testclimeet.shop$request_uri;
}

# 443 포트
server {
        listen 443 ssl;
        server_name www.testclimeet.shop;

        #ssl 인증서
        ssl_certificate /etc/letsencrypt/live/www.testclimeet.shop/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.testclimeet.shop/privkey.pem;

        location / {
                #스프링 포트로 포워딩
                proxy_pass http://localhost:8080;
        }
}
    

이후 enabled에 심볼릭 링크를 걸어주자

sudo ln -s 
/etc/nginx/sites-available/www.testclimeet.shop 
/etc/nginx/sites-enabled/www.testclimeet.shop

# 만약 해제하고 싶다면
sudo unlink /etc/nginx/sites-enabled/www.testclimeet.shop
심볼릭 링크 자체만 제거하는 것이기 때문에 원본 파일은 남아있다.

만약 스프링에서 ssl설정을 했줬다면 yml에서 ssl관련 코드를 지워야한다.

# nginx설정파일 이상 확인
sudo nginx -t
sudo systemctl reload nginx

nginx설정에 이상이 없는지 확인후 nginx 재시작까지 해준다면 아래와 같이 성공이다.

http://www.testclimeet.shop 이 443으로 포워딩 한번,8080으로 포워딩 된다.
gif에서 스웨거로 한번 더 바뀌는 이유는 yml에서 아래 설정을 해주었기 때문이다.

springdoc:
  swagger-ui:
    path: /

이제 3개월에 한번씩 갱신과 nginx재시작을 하도록 crontab을 작성해주면 인증서와 관련해 자동화는 끝나게 된다.
아직 클밋은 개발 과정에 있기에 crontab 설정은 배포 이후에 추가로 해주면 될 것 같다!

스프링이나 자바와 달리 개발 환경 설정 관련해서는 감자마냥 이해없이 따라만했다.
조금 더 시간이 걸리더라도 공식문서를 참고하며 한 줄 한 줄 이해에 기반한 코드를 작성해야함을 느꼈다.

참고: nginx.org - begginers_guide

profile
앞길막막 전과생

0개의 댓글