AWS 인프라를 세우는 작업이었다. 첫 스크립트를 돌리자마자 자격증명이 없다는 에러로 막혔고, 뒤에서는 “비밀값은 세션에 남기지 말라”고 직접 원칙을 세워놓고도 그 값을 확인하는 명령으로 키를 대화 기록에 그대로 남기는 사고를 냈다. 원칙은 맞았는데 그 원칙을 지키는 방법이 틀렸던 경우다. 이 글은 AWS 자격증명 안전하게 관리하려다 부딪힌 세 지점, 콘솔과 CLI 인증의 차이, 액세스 키 보관, 그리고 시크릿 확인 명령의 함정을 실제 사고 순서대로 정리한 것이다
콘솔에 로그인했는데 CLI는 자격증명이 없다고 한다
사용자가 AWS 계정을 만들고 콘솔에 로그인까지 마쳤다고 확인했다. 그런데 사전 점검 스크립트를 돌리자 이렇게 떴다
Unable to locate credentials. NoCredentials: Unable to locate credentials
브라우저 콘솔 로그인과 로컬 aws CLI의 자격증명은 완전히 별개다. 콘솔 로그인은 브라우저 세션일 뿐이고, CLI는 ~/.aws/credentials에 액세스 키가 저장돼 있어야 동작한다. 둘을 같은 것으로 착각하면 “분명 로그인했는데 왜 안 되지?”에서 한참을 헤맨다. 해결은 IAM 사용자를 새로 발급하는 것이었다. 콘솔에서 CLI 전용 사용자를 만들었다.
1. IAM 사용자 생성 — 콘솔 액세스 권한은 체크하지 않음 (CLI 전용) 2. 권한: "정책 직접 연결" → AdministratorAccess 3. 액세스 키 생성 — 사용 사례 "Command Line Interface(CLI)"
2번에서 주의할 게 있다. AdministratorAccess라는 정확한 이름의 정책을 붙여야 한다. AdministratorAccess-Amplify 같은 서비스 한정판이 목록에 섞여 있어서 무심코 고르면 권한이 모자라 나중에 또 막힌다
액세스 키 발급 화면의 경고를 어떻게 판단했나
키를 만들려는데 AWS가 화면에 경고를 띄웠다. 요지는 “장기 액세스 키 대신 AWS CLI V2의 aws login으로 콘솔 자격증명을 재사용하라”는 것이다. 브라우저 세션 기반의 임시 인증을 쓰라는 AWS의 최신 권장 방식이다
그래도 이번에는 전통적 액세스 키를 골랐다. 이유는 이번 작업의 성격 때문이다. 사전 점검부터 RDS 생성(available 대기가 5~10분 걸린다)까지 여러 스크립트가 끊김 없이 이어져야 했다. 중간에 세션이 만료되면 긴 스크립트가 끊긴다. 세션 만료 위험이 있는 임시 인증보다 장기 키가 이 상황엔 안전하다고 봤다
여기서 얻은 판단 기준은 이렇다. 자동화 스크립트가 길게 이어지는 상황에는 장기 액세스 키가, 사람이 매번 대화형으로 조작하는 상황에는 aws login 같은 임시 인증이 더 맞는다. AWS의 권장이 항상 모든 맥락에 맞는 건 아니다
다운로드한 키는 “보관”된 게 아니다
발급된 액세스 키는 .csv로 내려받게 된다. “다운로드했으니 안전하게 보관된 것 아니냐”는 질문이 나왔는데, 답은 아니오였다. Downloads 폴더의 평문 파일은 Spotlight 인덱싱, iCloud 동기화, 자동 백업 같은 경로로 노출 범위가 조용히 넓어진다
실무적으로 맞는 순서는 이렇다
1. aws configure 로 ~/.aws/credentials (권한 600) 에 등록됐으면 → csv는 더 이상 필요 없으니 삭제 2. 필요하면 비밀번호 관리자에 값만 옮겨둔다 3. 데모용 임시 키라면 작업 종료 후 삭제 또는 교체
기기를 바꿀 때 이 csv를 그대로 옮기면 되지 않냐는 질문도 있었는데, 이것도 아니다. 새 기기에서는 새 키를 발급하고 기존 키는 비활성화 후 삭제하는 게 맞다. 애초에 AWS는 발급 화면을 벗어나면 시크릿 값을 다시 보여주지 않기 때문에, “같은 키를 옮기기”는 csv를 미리 보관해두지 않았다면 기술적으로 불가능하기도 하다
사고 – 확인하려던 명령이 키를 대화창에 남겼다
가장 뼈아픈 지점이다. EC2에 외부 API 키를 채우는 단계에서, 셸 프로파일에 이미 있던 키를 재사용하기로 했다. 값이 맞는지 확인하려고 이런 명령을 실행했다
echo $API_SERVICE_KEY
문제는 이 명령을 AI 코딩 세션 안에서 실행했다는 것이다. 세션에서 실행한 명령의 출력은 그대로 대화 기록에 남는다. “비밀값은 세션에 남기지 말라”고 직접 안내해놓고, 정작 그 값을 확인하는 방법으로 출력이 기록에 남는 명령을 고른 것이다. 실행하는 순간 실제 API 키가 로그에 박혔다.
대응은 세 단계였다. 먼저 실수를 인정했다. 다음으로 이 키의 실제 위험도를 따졌다. 조회용 키라 자금이나 인프라 장악과는 무관했지만, 노출 자체는 되돌릴 수 없다는 점은 분명히 했다. 마지막으로 재발급 여부는 사용자 판단에 맡겼다. 재발급하면 연동된 여러 서비스가 다시 승인 대기에 들어갈 수 있다는 점을 함께 알렸다.
이후로는 규칙을 바꿨다. 확인이 필요한 비밀값은 세션 안의 어떤 명령으로도 거치지 않고, 완전히 별도의 터미널 창에서만 확인한다
편리한 도구가 정확히 반대로 작동할 때
세션에서 명령을 실행하고 그 출력을 바로 확인하는 방식은 평소엔 편하다. 진행 상황을 눈으로 즉시 볼 수 있으니까. 그런데 비밀값 앞에서는 이 편리함이 정확히 반대로 작동한다. “출력이 기록에 남는다”는 특성이 일반 작업에선 장점이고 시크릿에선 유출 경로다 물론 노출된 키가 조회용처럼 위험도가 낮은 경우도 있다. 그렇다고 이번 실수가 가벼워지는 건 아니다. 위험도가 낮았던 건 운이었고, 같은 습관으로 액세스 키를 확인했다면 결과는 전혀 달랐을 것이다
정리하면, 비밀값을 다루는 지시를 할 때는 그 값을 확인하는 방법 자체가 노출 경로가 되지 않는지 먼저 점검해야 한다. 콘솔 로그인과 CLI 인증을 구분하고, 다운로드한 키는 등록 후 삭제하고, 확인은 반드시 기록이 남지 않는 별도 터미널에서 한다. 이 세 가지는 AWS만이 아니라 시크릿을 만지는 모든 작업에 그대로 적용된다