SSL 인증서를 새로 발급받아 서버에 넣었다. 다음 배포 뒤에 만료된 인증서로 돌아가 있었다.
Table of contents
Open Table of contents
원인 — 배포가 그 파일을 덮었다
배포 스크립트가 이랬다.
rsync -avz --delete ./ deploy@web01:/var/www/shop/
인증서가 /var/www/shop/ssl/ 아래에 있었고 소스에도 같은 경로에 옛 인증서가 있다. rsync --delete 로 통째로 맞추니 배포할 때마다 소스의 옛 파일이 서버의 새 파일을 덮는다.
배포가 무엇을 덮는지 생각해 본 적이 없었다. 배포는 코드를 올리는 일이라고만 여겼는데 실제로는 대상 안의 모든 파일을 덮고 있었다.
주기가 다른 것을 갈랐다
무엇이 언제 누구에 의해 바뀌는지 적어 봤다.
| 자산 | 바뀌는 주기 | 바꾸는 주체 |
|---|---|---|
| 소스 코드 | 배포할 때 | 개발 |
| 인증서 | 1년 | 운영 |
| 설정 파일 | 환경 구성 시 | 운영 |
| 업로드 파일 | 계속 | 사용자 |
| 로그 | 계속 | 시스템 |
소스만 배포로 바뀌고 나머지는 다른 주기로 다른 사람이 바꾼다. 갱신 주기가 다른 것이 배포 대상 안에 있으면 배포가 덮는다.
섞여 있으면 한쪽 동작이 다른 쪽을 지운다. 갈라 보니 배포 대상에 있으면 안 되는 것이 몇 가지 나왔다.
자리를 나누고 소스에서 지웠다
배포 대상 밖으로 옮겼다.
/var/www/shop/ 배포 대상 (소스만)
/etc/shop/ssl/ 인증서
/etc/shop/ 설정
/data/shop/upload/ 업로드
/var/log/shop/ 로그
웹 서버 설정이 새 경로를 가리키게 바꿨다.
SSLCertificateFile /etc/shop/ssl/cert.pem
SSLCertificateKeyFile /etc/shop/ssl/privkey.pem
업로드는 /var/www/shop/upload 를 /data/shop/upload 로 잇는 링크로 두고 rsync 제외 목록에 넣었다.
옮기고 나서 소스에 남은 옛 인증서를 지웠다. 안 지우면 또 덮인다.
ssl/
*.pem
*.key
config/db.conf
무시 목록에도 넣었다. cert.pem 과 privkey.pem 은 애초에 소스에 있으면 안 됐는데 한 번 커밋되면 지워도 이력에 남기 때문이다. 이력에 든 것은 별도로 정리했고 그 인증서는 이미 만료된 뒤라 위험이 낮았다.
검증 — 배포가 안 건드려야 할 것
인증서를 옮긴 김에 만료 확인도 넣었다.
#!/bin/sh
CERT=/etc/shop/ssl/cert.pem
END=$(openssl x509 -enddate -noout -in "$CERT" | cut -d= -f2)
DAYS=$(( ($(date -d "$END" +%s) - $(date +%s)) / 86400 ))
echo "만료: $END (${DAYS}일 남음)"
[ "$DAYS" -lt 30 ] && echo "갱신이 필요합니다"
openssl x509 -enddate 로 한 달 전에 알린다. 전에는 만료돼서 접속이 안 될 때 알았다.
배포가 다른 것을 안 건드리는지 확인하는 것도 넣었다.
BEFORE=$(ssh $H 'md5sum /etc/shop/ssl/cert.pem /etc/shop/db.conf')
deploy
AFTER=$(ssh $H 'md5sum /etc/shop/ssl/cert.pem /etc/shop/db.conf')
[ "$BEFORE" = "$AFTER" ] || { echo "배포가 관리 대상 밖 파일을 바꿨습니다"; exit 1; }
배포 전후 md5sum 이 같아야 한다. 다르면 배포 범위가 잘못된 것이다. 무엇을 바꿨는지만 보면 이 문제를 못 잡는다.
배포 대상 안에 있으면 안 되는 것도 찾아봤다.
$ ssh $H 'find /var/www/shop -newer /var/www/shop/index.php -not -path "*/upload/*" | head -20'
find -newer 로 배포 시각보다 새로운 파일이 나오는데 배포로 안 만들어진 것들이다. 캐시와 세션과 임시 업로드와 로그 넷이 나왔고 전부 밖으로 뺐다.
정리
- 갱신 주기가 다른 자산이 배포 대상 안에 있으면 배포가 덮는다
- 배포는 대상 안의 모든 파일을 덮는다
- 무엇이 언제 누구에 의해 바뀌는지 적어 보면 갈린다
- 배포 대상은 소스만 두고 나머지는 밖에 둔다
- 소스에서 지워야 또 안 덮인다. 무시 목록에도 넣는다
- 인증서와 키는 애초에 소스에 있으면 안 된다. 이력에 남는다
openssl x509 -enddate로 만료를 미리 알린다md5sum으로 배포가 무엇을 안 건드렸는지도 확인한다find -newer로 배포 시각보다 새로운 파일을 찾으면 밖으로 뺄 것이 나온다