🗯️ 문제
기존 설계에서 https
설계 단계에서는 https의 도입은 고려하지 않았습니다.
그 이유는 security에 대한 숙련도가 낮고 기능 개발에 좀더 집중했기 때문에 https 설정을 하지 않아도 기본적인 기능이 수행될 것이라 생각했기 때문입니다.
https로의 전환 이유?
https로 전환하기로 한 이유는 2가지입니다. 보안 이슈와 Mixed content 이슈 입니다.
1. 보안 이슈
현재 개발 단계에서는 외부에 페이지를 개방하지 않기 때문에 문제가 발생하지 않을 수 있지만, 나중을 생각하면 https의 도입을 필수로 해야한다는 멘토님의 조언이 있어서 도입을 고려했습니다.
2. 프론트의 Mixed content 이슈


프론트엔드 서버에서 https로 배포했기 때문에 http로 배포된 백엔드 api 호출 시 Mixed content 에러가 발생하고, 해결하기 위해서는 https로 백엔드 서버를 배포하는 방법이 있었습니다. Mixed content란?
이런 이유들로 https를 적용하기로 했습니다.
🔥 해결 방법
1. 인증되지 않은 SSL 인증서 발급
첫번째로, 프로그래머스 데브코스 강의 중 java의 기본 명령어인 keytool을 이용해 인증되지 않은 ssl 인증서를 생성하는 방법을 배웠는데, 이 방법을 사용하기로 했습니다.
keytool -genkey -alias prgrms_keystore -keyalg RSA -storetype PKCS12 -keystore prgrms_keystore.p12 # keystore 생성 keytool -export -alias prgrms_keystore -keystore prgrms_keystore.p12 -rfc -file prgrms.cer # keystore에서 인증서 추출 keytool -import -alias prgrms_truststore -file prgrms.cer -keystore prgrms_truststore.p12 # trust-store 생성
해당 방법은 신뢰할 수 있는 인증기관에서 발급받은것이 아닌 사설 인증서이기 때문에 아래와 같은 에러가 발생했습니다.

2. 인증된 SSL 인증서 발급
기존의 방법으로는 보안 문제가 완전히 해결이 되지 않았기 때문에 인증된 SSL 인증서를 발급받아야 했습니다. Let’s Encrypt를 사용하여 발급받았습니다.
2-1. 도메인 주소 발급
ssl 인증서 발급에는 선행 조건이 필요합니다. 바로 서버에 연결하기 위한 도메인 주소입니다.
보통 도메인 발급은 유료이지만, 몇몇의 무료 도메인 발급 사이트를 통해 일정 기간동안 무료로 사용할 수 있기 때문에 무료 도메인을 발급받았습니다.
해당 홈페이지의 회원가입 후 원하는 도메인을 입력해 주소를 할당받았습니다.

그리고, 아래 그림처럼 IP연결란에 서버의 ip주소를 입력해 서버와 연결합니다.

입력이 완료되면, IP 주소 대신 도메인 주소 입력으로 해당 IP에 접속할 수 있게 됩니다.
2-2. Let's Encrypt 인증서 발급
Let's Encrypt 인증서 발급에는 여러가지 방법이 있지만, 여기서는 Certbot을 이용했습니다.
# ubuntu에서 certbot 설치 apt install software-properties-common add-apt-repository universe add-apt-repository ppa:certbot/certbot apt update apt upgrade apt install certbot python3-certbot-apache
인증서 발급을 위해서는 3가지의 과정을 거칩니다.
- Certbot 인증서 요청
- 요청한 도메인 소유주 확인
- 인증서 발급
그리고, 도메인 소유주 확인을 위한 방법에는 3가지가 있습니다.
- standalone - 가상 웹서버를 가동하여 도메인소유주 확인
- webroot - 자신의 웹서버가 제공하는 특정 파일로 도메인소유주 확인
- dns - dns 레코드에 특정 값을 작성하여 도메인소유주 확인
여기서는 서버를 종료해도 아무런 문제가 없었기 때문에 1번 방법을 사용했습니다. 서버를 중단할 수 없을 경우 2번 방법을 사용합니다.
먼저, 인증서 발급에 80번 포트가 사용되기 때문에 aws에서 인바운드 포트가 열려있는지 확인한 후 진행합니다.
# ssl 인증서 발급 sudo certbot certonly --standalone
[sudo] password for dev: <root password> Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator standalone, Installer None Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): # 이메일 입력 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y # 약관 동의 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing, once your first certificate is successfully issued, to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y # 이메일 정보 수신 동의 Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): # 인증서를 발급할 도메인 입력 Requesting a certificate for everevent.kro.kr IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/vompressor.com/fullchain.pem # 발급된 인증서 경로 Your key file has been saved at: /etc/letsencrypt/live/vompressor.com/privkey.pem # 발급된 인증서 경로 Your certificate will expire on 2021-05-16. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
이 중 기억할 부분은 도메인 입력과 인증서 경로입니다.
위의 도메인 발급 사이트에서 발급받고, 해당 aws 서버와 연결한 도메인 주소를 정확히 입력해야 합니다.
그리고, 해당 인증서 경로에 관련 파일들이 생성됩니다.
2-3. 인증서를 Spring Boot 프로젝트와 연결하기
처음 인증서를 발급받으면
/etc/letsencrypt/live
경로에 인증서 관련 파일들이 저장됩니다.폴더 접근은 root 계정만 가능하기 때문에
sudo -s
로 전환 후 접근합니다.
폴더에는 다음과 같이 발급한 도메인 주소명으로 되어있는 폴더가 생성되어 있습니다.

현재는 이미 발급한 다른 인증서들이 포함되어있지만, 초기에 접근할 시 민트색의 4개의 파일 + README만 존재합니다.
해당 키들의 용도는 다음과 같습니다.
- privkey.pem : 개인키
- fullchain.pem : 내 기본 공개키 + 기타 정보를 포함한 공개 키
- cert.pem : 기본 공개키
- chain.pem : 기타 정보를 포함한 공개키
이제 프로젝트에 적용할 key를 생성할 것입니다.
openssl pkcs12 -export -in cert.pem -inkey privkey.pem -out [생성할 p12 파일명.p12] -name [별칭] -CAfile chain.pem -caname root keytool -importkeystore -deststorepass [인증서 password] -destkeypass [인증서 password] -destkeystore [생성될 jks 파일명.jks] -srckeystore [생성한 p12파일] -srcstoretype PKCS12 -srcstorepass [PKCS12에서 사용한 암호] -alias [위에서 사용한 별칭] keytool -import -trustcacerts -alias root -file chain.pem -keystore [생성한 jks 파일]
마지막 import까지 하게되면 인증서 관련된 작업은 모두 종료됩니다.
이제 Spring boot 프로젝트로 돌아와 application.yml 파일을 작성합니다.
위에서 생성한 jks 파일을 resources 폴더에 옮긴 후 아래와 같이 작성합니다.
server: port: 443 ssl: enabled: true key-store: classpath:everevent.jks key-store-password: # 인증서 password key-password: # 인증서 password
이렇게 되면 모든 설정이 끝납니다.
주의할 점은 이렇게 https로 설정한 api에 접근 시 도메인 명으로 접근해야 ssl 인증서 확인이 가능합니다. 기존의 IP주소로 접근할 경우 이전과 같은 경고문구가 계속 발생합니다.
ex)
https://everevent.kro.kr/test
🕑 해결해야할 사항
https 적용은 성공했지만 해당 방법에는 몇가지의 문제가 존재합니다.
- 도메인 주소의 유효기간
- SSL 인증서의 유효기간
- jks 파일이 resource 폴더 내부에 있어 public으로 노출됨
1번의 경우는 다른 무료 도메인 발급 사이트, 또는 유료로 발급받아 해결 가능합니다. (멘토님이 공유해주신 링크 참고 : https://cloud-oky.tistory.com/348)
2번의 경우는 자동으로 SSL을 갱신하는 설정을 추후에 설정할 경우 해결 가능합니다.
3번은 여러가지 해결 방법이 존재하는데, 서브모듈로 jks 파일의 위치를 옮기는 방법과 서버에 nginx를 띄워 nginx에 ssl 인증서를 발급하는 방법 입니다. 이부분은 추후의 리팩토링을 통해 방향을 결정해야 한다고 생각합니다.
📖 참고문서
certbot ubuntu 설치 : https://www.manualfactory.net/13639
ssl 인증서 발급 : https://www.vompressor.com/tls1/
프로젝트에 ssl키 적용하기 : https://elfinlas.github.io/2018/03/19/spring-boot-tls-certbot/