계정 구조를 정리하게 됐다. 최상위 계정 하나로 배포와 조회와 설정 변경과 결제를 전부 하고 있었다.
Table of contents
Open Table of contents
최상위로 전부 하던 상태
한 계정으로 전부 하면 그 계정 정보가 새는 순간 전부 뚫린다. 그리고 누가 무엇을 했는지가 안 갈린다. 기록에 전부 같은 계정으로 찍히기 때문이다.
두 문제가 성격이 달랐다. 앞은 사고가 났을 때의 피해 범위이고 뒤는 사고가 났는지조차 알기 어렵게 만드는 조건이다.
최상위를 평소에 안 쓰게
최상위 계정은 결제 정보 변경이나 계정을 닫는 것처럼 그 계정으로만 할 수 있는 일에만 쓰기로 했다. 다중 인증을 걸고 비밀번호를 별도로 보관하고 쓸 일이 생기면 기록을 남기게 했다.
접근 키를 지운 것이 그중 컸다. 키가 있으면 사람이 안 써도 프로그램이 쓸 수 있고 그러면 평소에 안 쓴다는 규칙이 규칙으로 성립하지 않는다.
사용 자체를 알림 대상으로도 걸었다. 평소에 안 쓰는 계정이므로 쓰였다는 사실 자체가 신호가 된다. 실제로 한 번 걸렸는데 결제 정보를 바꾸느라 쓴 것이었고 정상이었지만 알림이 온 것이 맞았다.
하는 일로 나눈 역할
역할을 배포와 운영과 개발과 읽기 전용 넷으로 나눴다. 사람으로 나누지 않고 하는 일로 나눈 것이 요점이었다.
한 사람이 여러 역할을 가질 수 있게 하고 평소에는 읽기 전용으로 있다가 필요할 때 역할을 바꾸게 했다. 바꾸는 행위가 기록에 남으므로 언제 무엇을 하려고 권한을 올렸는지가 따라온다.
넓게 주고 좁히는 순서
권한은 처음에 넓게 주고 실제 사용을 보고 좁혔다. 처음부터 좁게 주면 무엇이 필요한지 모르는 채로 계속 막히고 그때마다 급하게 권한을 늘리게 된다.
$ aws cloudtrail lookup-events --lookup-attributes AttributeKey=Username,AttributeValue=deploy \
--query 'Events[].EventName' --output text | tr '\t' '\n' | sort | uniq -c
배포 계정이 실제로 부른 것을 세니 네 종류뿐이었고 나머지 권한을 뺐다. 좁힌 뒤에는 며칠 동안 거부된 요청을 봤다. 두 건이 나왔고 하나는 필요한 것이라 다시 넣었으며 하나는 안 쓰는 기능이었다.
넓게 주고 좁히는 순서가 성립하려면 좁힌 뒤에 무엇이 막히는지를 볼 수단이 있어야 한다. 그 수단이 없으면 좁히는 것 자체가 위험해진다.
퇴사와 프로그램 계정
사람이 나갈 때의 순서도 정했다. 역할에서 먼저 빼면 즉시 막히고 계정 비활성화와 자원 인계를 거쳐 마지막에 계정을 지운다. 계정을 먼저 지우면 그 사람이 만든 자원의 소유가 사라져 인계가 어려워진다.
프로그램이 쓰는 계정도 나눴다. 배포 도구와 모니터링과 백업 스크립트가 한 키를 공유하고 있어서 하나가 새면 셋이 다 뚫리는 상태였다. 각각 필요한 권한만으로 따로 발급하니 하나를 회수해도 나머지가 돌고 기록에서 누가 무엇을 했는지도 갈렸다.
프로그램 키는 사람 계정보다 오래 살아 있어서 더 위험했다. 만료를 걸고 갱신 절차를 만들어 두지 않으면 몇 년 전에 만든 키가 계속 유효한 상태로 남는다.
정리
- 최상위 계정으로 전부 하면 새면 전부 뚫리고 누가 했는지 안 갈린다
- 피해 범위 문제와 추적 불가 문제는 성격이 다르다
- 최상위를 평소에 안 쓰게 하고 접근 키를 지운다
- 키가 있으면 안 쓴다는 규칙이 성립하지 않는다
- 사람이 아니라 하는 일로 역할을 나눈다
- 권한은 넓게 주고 실제 사용을 보고 좁힌다
- 좁힌 뒤 무엇이 막히는지 볼 수단이 있어야 좁힐 수 있다
- 나갈 때 역할에서 먼저 빼고 계정은 나중에 지운다