No Credentials Error 해결하기
배경
당첨자 리스트를 엑셀파일로 생성해 다운로드 링크를 반환하는 API를 구현했다.
다만 로컬에서는 정상적으로 잘 작동하는데 ec2에 배포되니 NoCredentialsError가 발생한다.
- 버그에 대한 이슈 만들기
- 원인 파악하기
- 작업
- PR
1. 원인 파악하기
NoCredentialsError는 AWS SDK에서 자격 증명(credential)을 찾을 수 없을 때 발생하는 오류이다.
이 오류는 AWS 서비스에 연결하려고 할 때 해당 서비스에 액세스하기 위한 자격 증명이 없을 때 발생한다.
즉, AWS 계정에 대한 액세스 키(ID 및 시크릿 키)가 설정되지 않았거나 올바르게 설정되지 않은 경우에 발생할 수 있다.
현재는 fastapi 코드 내의 config.py 파일에 AWS SDK 정보가 하드코딩 되어있다.
현재 엑셀파일 생성-제공 API 는 AWS S3 버킷 서비스를 사용하기 위해 boto3를 사용해서 AWS 서비스에 접근한다.
boto3에서 AWS 인증정보를 체크하고 원하는 서비스에 접근하는데, 이 과정에서 인증정보를 확인하지 못하고 있는것으로 생각된다.
boto3는 다음과 같은 순서로 인증정보를 확인한다.
1. 환경변수 확인 :
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 등 환경변수가 설정되어 있는지 확인
2. AWS 자격증명 프로파일 확인 :
~/.aws/credentials 파일 또는 지정된 위치의 자격증명 프로파일 파일에서 AWS 자격증명 프로파일을 찾는다. 이 파일에는 하나 이상의 aWS 자격증명 프로파일이 포함될 수 있으며 각 프로파일에는 액세스 키 ID와 시크릿 액세스 키가 포함된다.
3. IAM 역할 :
4. AWS 자격증명 공급자 체인
위 방법 중에서 하나라도 사용가능한 자격증명을 찾으면 boto3는 해당 자격증명을 사용해서 AWS 서비스에 액세스하고, 하나라도 해당되는 자격 증명을 찾지 못하면 NoCredentialsError를 반환한다.
로컬에서 정상작동되는 로그를 살펴보면 boto3가 2번 방법으로 자격증명을 찾았다.
2024-04-17 19:05:44,634 - botocore.credentials - INFO - Found credentials in shared credentials file: ~/.aws/credentials
2024-04-17 19:05:46,150 - uvicorn.access - INFO - 127.0.0.1:55232 - "GET /api/v1/reward-draws/excel-download?eventId=455fcfd7-825d-4abe-94ac-a0c06e343601 HTTP/1.1" 200
ec2의 도커 컨테이너 로그를 확인하면 boto3가 자격증명을 찾지 못하고 NoCredentialsError를 띄웠다.
2번 방법은 AWS CLI를 이용해서 자격증명 파일을 만들어두는것인데, 로컬에서는 언젠가 CLI를 사용해보면서 자동으로 증명 파일이 생성되어서 문제없이 코드가 작동한것 같다.
하지만 ec2에서는 해당 방법을 쓰기 힘드므로 config.py에 저장된 증명정보를(아직 하드코딩되어있다) session을 만들어서 boto3가 s3클라이언트 객체를 생성할때 입력할 수 있게 하는 방식을 사용하는 것이 좋을것 같다.
2. 작업
기존에는 s3 클라이언트 객체를 생성할때 바로 boto3 를 사용했다.
s3 = boto3.client('s3')
bucket_name = 's3 버킷명'
prefix = event.title # 가져올 오브젝트들의 접두사
s3_response = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
이때 boto3가 호출되며 위에 나열한 몇가지의 인증정보 찾기 단계를 거치는데, 그중 프로파일 검색에서 인증정보가 있어서 로컬에서는 정상작동했다.
session = boto3.session.Session(
aws_access_key_id = settings.aws_access_key_id,
aws_secret_access_key = settings.aws_secret_access_key,
region_name = settings.aws_region
)
s3 = session.client('s3')
이 방식은 boto3를 사용해서 새로운 객체를 생성하고 이 세션을 통해 클라이언트 객체를 생성하는 방식이다.
세션 객체를 생성할 때 직접 AWS 자격증명을 지정할 수 있으므로 특정 자격 증명을 사용해서 여러개의 클라이언트 객체를 생성할 수 있는 방법이다.
또한 boto3가 위에서 설명했던 모든 방식으로도 자격증명을 찾지 못했을때도 직접 증명을 때려넣으니 NoCredentialsError가 발생할 일이 없다,,
'프로젝트 > 작업' 카테고리의 다른 글
[project - KWJ] 서버이전, GitHub CI/CD 수정하기 (0) | 2024.03.02 |
---|