website: logviewer 계정 실제 등록 완료 반영, 그리고 nologin 함정
순서는 단순했다. `logviewer` 시스템 계정을 만들고, `/home/ubuntu`에 `setfacl -m u:logviewer:x`로 통과 권한만 얹었다. chmod로 전체 공개하는 대신 ACL로 이 계정만 통과시키는 방식을 택한 이유는 `/home/ubuntu` 자체를 열어버릴 필요가 없었기 때문이다. 실제로 로그가 쌓이는 `website/i...
#414에서 설계했던 logviewer 계정 접근 방식을 실제 서버에 적용하고, 그 결과를 문서에 반영한 PR이다.
#414는 로그 접근을 위한 계정 구조와 권한 설계를 정리한 문서였고, 이번 PR은 그걸 실제로 서버에 올린 뒤 "설계대로 됐는지"를 확인하고 기록하는 작업이었다. 문서 diff만 보면 3줄 추가, 1줄 삭제로 아주 작지만, 그 안에 담긴 건 서버 작업 전체다.
키 등록은 새로 만들지 않고 안시현·신선우가 기존에 dbclient에 등록해뒀던 공개키를 그대로 authorized_keys에 재활용했다. 계정을 새로 파는 김에 키까지 새로 발급받게 하는 것보다, 이미 검증된 키를 재사용하는 쪽이 관리 부담도 적고 실수할 여지도 적다고 봤다.
여기까지는 계획대로 흘러갔는데, 계정 셸을 정하는 부분에서 걸렸다. 처음엔 당연히 /usr/sbin/nologin으로 만들었다. 어차피 forced command로만 접근하게 할 거고, 대화형 로그인은 필요 없으니 nologin이 맞다고 생각했다. 그런데 실제로 붙여보니 forced command 자체가 동작하지 않았다. 이유를 따져보니 sshd는 authorized_keys의 command=를 그 계정의 로그인 셸을 통해 실행하는데, 셸이 nologin이면 어떤 명령이 들어오든 무조건 무시하고 즉시 거부해버린다. 결국 forced command든 뭐든 셸 자체가 안 도는 거였다.
그래서 dbclient가 원래 쓰던 방식대로 /bin/bash로 정정했다. 대신 보안은 셸을 막는 걸로 확보하는 게 아니라 command= 강제와 no-pty(대화형 세션 차단) 조합으로 가져가는 쪽으로 이해를 바꿨다. 셸을 열어두되 들어올 수 있는 통로 자체를 강제 명령 하나로 좁히는 방식이다. 이 함정은 문서에 그대로 적어뒀다 — 나중에 비슷한 계정을 또 만들 사람(그게 나 자신이어도)이 같은 삽질을 반복하지 않도록.
검증은 더미 UUID로 했다. 정상 형식의 요청 ID를 넣으면 grep을 시도해서 "일치하는 로그 없음"이 나오고, 비정상 형식을 넣으면 즉시 차단되는 걸 확인했다. 다만 실제 요청 ID로 로그가 찾아지는 건 #404가 dev에 머지되고 배포된 이후부터다 — 그 전에는 로그에 reqId 자체가 안 찍히기 때문에, 지금 이 계정으로 뭘 검색해도 나올 게 없는 게 정상이다. 이 타이밍 문제도 헷갈릴 수 있어서 문서에 같이 남겼다.
정리하면 이번 PR은 코드를 바꾼 게 아니라 실제로 서버에서 벌어진 일을 문서에 사후 반영한 것에 가깝다. "문서 따로, 실제 작업 따로"가 되지 않게 하려고 계획(#414)과 실행 결과(#415)를 분리해서 남겨둔 셈이다.