통합과 배포 · 인증과 TLS · 실습
401 과 403, 그리고 인증서
목표
401 과 403 을 단서로 인증 문제의 계층을 좁히고, 인증서 실패 모드를 파일에서 직접 확인할 수 있게 됩니다.
왜 중요한가
401 은 인증 실패입니다 — "네가 누구인지 확인할 수 없다". 403 은 인가 실패입니다 — "누구인지는 알겠는데 이건 못 하게 돼 있다". 이 구분이 조사 방향을 정반대로 가릅니다. 401 이면 자격 증명 자체를 보고, 403 이면 자격 증명은 건드릴 필요 없이 권한 설정을 봅니다. "권한 오류" 라고 뭉뚱그리면 엉뚱한 쪽을 몇 시간 팝니다.
그리고 401 안에서도 이유가 갈립니다. 토큰 없음, 알 수 없는 토큰, 만료된 토큰이 전부 401 이지만 대응이 다르므로 응답 본문의 사유 문자열을 함께 봐야 합니다.
인증서 쪽에서는 두 가지를 확인합니다. 만료는 notAfter 로 보는데, 이때 현재 시각도 함께 찍어야 합니다 — 시계가 틀린 클라이언트에서 멀쩡한 인증서가 만료로 보이는 일이 상당히 많기 때문입니다. 이름 불일치는 CN 이 아니라 SAN 을 봐야 하지만, 이 실습의 인증서는 CN 만 가지고 있으므로 주체 이름으로 확인합니다.
토큰 네 가지 — (헤더 없음), expired-token-2025, readonly-token, fde-prod-2026
인증서 두 개 — /opt/data/tls/expired.pem, /opt/data/tls/wronghost.pem (접속하려던 이름은 api.customer.example)
단계
1. /opt/app/authapi.py 를 실행해 127.0.0.1:8003/public 이 200 을 반환하게 만드세요.
2. Authorization 헤더 없이 /private 를 호출한 상태 코드를 /root/auth/no_token.txt 에 적으세요.
3. expired-token-2025 로 /private 를 호출한 응답 본문을 /root/auth/expired_reason.txt 에 저장하세요.
4. readonly-token 으로 /private 를 호출한 상태 코드를 /root/auth/readonly.txt 에 적으세요.
5. fde-prod-2026 으로 /private 를 호출한 상태 코드를 /root/auth/ok.txt 에 적으세요.
6. expired.pem 의 만료일을 /root/auth/cert_expiry.txt 에 저장하세요.
7. wronghost.pem 의 주체 이름을 /root/auth/cert_cn.txt 에 저장하세요.
8. /root/auth/report.md 에 401 과 403 의 차이, 그리고 두 인증서의 문제를 정리하세요. 두 상태 코드와 api.other.example, 만료 연도가 들어가야 합니다.
참고
curl -s -o /dev/null -w '%{http_code}' -H 'Authorization: Bearer 토큰' http://127.0.0.1:8003/privateopenssl x509 -in 파일 -noout -enddate -subject- 현재 시각과 비교하려면
date -u를 함께 찍어 보세요. - 흔한 실수 1: 3번에서 상태 코드만 저장하는 것. 401 의 이유가 필요합니다.
- 흔한 실수 2: 헤더 형식을
Bearer없이 토큰만 보내는 것. 그러면 토큰이 아예 인식되지 않습니다.
단계 8개
- 인증 게이트웨이 띄우기
- 토큰 없이 호출해 보기
- 만료 사유 확보하기
- 권한 부족 확인하기
- 정상 인증 확인하기
- 만료된 인증서 확인하기
- 이름이 다른 인증서 확인하기
- 진단 보고서 쓰기