회전하지 않아도 되는 비밀값
한 줄 요약
앞의 실습들은 전부 오래 사는 비밀값을 다뤘습니다. 동적 비밀값은 요청할 때마다 새로 만들어지고 짧은 시간 뒤 스스로 사라지는 자격 증명입니다. 새어 나가도 곧 쓸모가 없어지므로, 회전을 사람이 기억해야 하는 일에서 시스템의 기본 동작으로 바꿉니다.
왜 필요한가
이 코스에서 한 일을 돌아보면 같은 패턴이 반복됩니다. 값이 새고, 새 값을 만들고, 그 값을 쓰는 모든 곳(DB, 파일, 서비스 메모리)을 맞추고, 옛 값이 거절되는지 확인했습니다. 서비스가 열 개, 환경이 셋이면 이 일은 금방 아무도 하지 않는 일이 됩니다. 비밀번호가 몇 년째 그대로인 서버가 많은 이유입니다.
또 오래 사는 비밀값은 "누가 쓰고 있나" 에 답하기 어렵습니다. 한 비밀번호를 서비스 셋과 사람 둘이 함께 쓰면, 로그에 남은 사용이 누구의 것인지 구별할 수 없습니다.
어떻게 동작하나
HashiCorp Vault(또는 그 분기인 OpenBao)의 데이터베이스 시크릿 엔진이 대표적인 예입니다.
| 순서 | 일어나는 일 |
|---|---|
| 1 | 서비스가 자기 신원(쿠버네티스 서비스 계정 토큰, 클라우드 IAM 역할 등)으로 Vault 에 로그인한다 |
| 2 | 서비스가 "주문 DB 읽기 계정" 을 요청한다 |
| 3 | Vault 가 DB 에 접속해 이름이 무작위인 계정을 지금 만들고, 비밀번호와 함께 돌려준다 |
| 4 | 그 자격 증명에는 임대 기간(lease, 예를 들어 1시간)이 붙는다 |
| 5 | 기간이 끝나면 Vault 가 DB 에서 그 계정을 지운다. 서비스는 필요하면 다시 요청하거나 갱신한다 |
여기서 바뀌는 것이 셋입니다. 비밀값의 수명이 몇 년에서 몇 시간으로 줄고, 서비스마다 다른 계정이 생겨 로그에서 주체가 구별되며, 사고가 나면 그 임대만 즉시 폐기(revoke)할 수 있습니다.
쿠버네티스에서는 External Secrets Operator 가 Vault 나 클라우드 비밀 관리자에서 값을 가져와 Secret 으로 만들어 줍니다. 이 경우 Secret 은 원본이 아니라 사본이므로, 앞 모듈의 저장 암호화와 RBAC 은 여전히 필요합니다.
현장에서 만나는 모습
동적 비밀값으로 가는 길의 가장 큰 벽은 비밀값 0번 문제입니다. Vault 에 로그인하려면 무엇인가 신원이 필요한데, 그것이 또 하나의 오래 사는 비밀값이면 문제를 옮긴 것뿐입니다. 그래서 플랫폼이 이미 보증하는 신원(쿠버네티스 서비스 계정 토큰, 클라우드 인스턴스 신원)으로 로그인하게 설계합니다.
두 번째 벽은 앱입니다. 기동할 때 한 번 비밀번호를 읽는 앱은 임대가 끝나면 연결이 끊깁니다. 연결 풀이 새 자격 증명을 다시 읽도록 고치거나, 사이드카가 파일을 갱신하고 앱이 그 파일을 다시 읽게 해야 합니다. 이 코스에서 본 "다시 읽히지 않은 서비스" 문제가 여기서 매시간 일어난다고 생각하면 됩니다.
모든 것을 한 번에 바꾸려 하지 말고, 노출 위험이 가장 큰 것(사람이 공유하는 DB 관리자 계정, CI 의 클라우드 키)부터 옮기는 것이 보통입니다.
이 코스의 실습과 견주어 보기
앞 실습들을 동적 비밀값의 눈으로 다시 보면 무엇이 달라지는지 분명해집니다.
| 앞 실습의 일 | 동적 비밀값이라면 |
|---|---|
| 기록에서 찾은 토큰을 손으로 회전 | 토큰이 한 시간 뒤 스스로 사라진다 |
| 외주 개발자가 떠날 때 데이터 키와 값 회전 | 그 사람의 신원으로는 새 임대를 받을 수 없게 하면 끝난다 |
| 보고용 계정이 읽은 비밀번호를 회전 | 그 계정이 받은 임대만 폐기한다 |
| 디버그 로그에 남은 비밀번호 정리 | 남은 값은 이미 만료돼 쓸모가 없다(정리는 여전히 한다) |
반대로 동적 비밀값이 대신해 주지 않는 것도 있습니다. 비밀값이 어디에 찍히는지(로그, 프로세스 목록), 누가 요청할 권한을 갖는지(Vault 정책, RBAC), 사본이 어디에 놓이는지(쿠버네티스 Secret)는 여전히 직접 지켜야 합니다. 동적 비밀값은 회전의 부담을 덜어 줄 뿐, 노출 경로를 막는 일을 없애 주지는 않습니다.
English corner
- dynamic secrets: 요청할 때 만들어지는 비밀값. 반대말은 static secrets 입니다.
- lease / TTL: 임대와 수명. "the credential is valid for the lease duration" 처럼 씁니다.
- revoke: 폐기. 기간 전이라도 즉시 무효로 만듭니다.
- secret zero: 비밀값을 받아 오기 위해 필요한 첫 비밀값. 설계 문서의 단골 질문입니다.
다음 퀴즈에서 할 것
동적 비밀값이 무엇을 해결하고 무엇을 남기는지, 앞 실습들과 견주어 확인합니다.
한 걸음 더 — 어디서부터 바꾸나
동적 비밀값으로 전부 한 번에 옮기는 조직은 없습니다. 보통 가장 위험한 것부터 옮깁니다 — 여럿이 공유하는 데이터베이스 관리자 계정, CI 가 들고 있는 클라우드 키처럼 새면 피해가 크고 공유 범위가 넓은 것입니다. 그다음 앱이 자격 증명을 다시 읽는 구조(연결 풀 갱신, 파일 재적재)를 갖춘 서비스로 넓혀 갑니다. 이 순서를 지키면 같은 노력으로 위험이 가장 많이 줄고, 앱 수정이 큰 서비스는 뒤로 미룰 수 있습니다. 중요한 것은 '정적 비밀값을 0으로 만든다' 가 아니라 '남은 정적 비밀값이 무엇이고 왜 아직 정적인지' 를 언제나 말할 수 있는 상태입니다.