본문 바로가기

AWS

Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain 이슈

728x90

AWS에는 다양한 자격증명 방법이 있는데 보통 Access key랑 Secret key를 이용한 임시 자격 증명과 EC2 IAM Role 자격증명 등이 있다.

EC2에 Access key랑 Secret Key를 입력해두고, EC2에서 S3로의 Get, Put 등 작업을 해야하는데 이런 이슈가 나타났다.

 

이슈 전문

 [ERROR] c.h.o.e.exception.ExceptionAdvice - ExceptionAdvice(handleRunTimeException) => ErrorResultRes(success=false, data=null, error=ErrorRes(errorCode=E0002, errorMsg=RuntimeException)) [Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain(credentialsProviders=[SystemPropertyCredentialsProvider(), EnvironmentVariableCredentialsProvider(), WebIdentityTokenCredentialsProvider(), ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])), ContainerCredentialsProvider(), InstanceProfileCredentialsProvider()]) : [SystemPropertyCredentialsProvider(): Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId)., EnvironmentVariableCredentialsProvider(): 
Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId)., WebIdentityTokenCredentialsProvider(): Either the environment variable AWS_WEB_IDENTITY_TOKEN_FILE or the javaproperty aws.webIdentityTokenFile must be set., ProfileCredentialsProvider(profileName=default, 
profileFile=ProfileFile(sections=[])): Profile file contained no credentials for profile 'default': ProfileFile(sections=[]), ContainerCredentialsProvider(): Cannot fetch credentials from container - neither AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variables are set., InstanceProfileCredentialsProvider(): Failed to load credentials from IMDS.]]

 

 

이슈 해석

- SystemPropertyCredentialsProvider(): 시스템 속성(aws.accessKeyId, aws.secretAccessKey)에서 자격 증명을 찾지 못했습니다.

- EnvironmentVariableCredentialsProvider(): 환경 변수(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)에서 자격 증명을 찾지 못했습니다.
- WebIdentityTokenCredentialsProvider(): 웹 ID 토큰 (IAM Roles for Service Accounts 등)을 찾지 못했습니다.
- ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])): ~/.aws/credentials 파일의 default 프로필에서 자격 증명을 찾지 못했습니다.
- ContainerCredentialsProvider(): ECS/EKS 컨테이너 환경에서 사용하는 컨테이너 자격 증명을 찾지 못했습니다.
- InstanceProfileCredentialsProvider(): EC2 인스턴스 프로파일 (IAM Role)에서 자격 증명을 찾지 못했습니다.

 

 

이슈 결론

: 너 자격증명 없는데?

 

 

근데 EC2에 접속해서 들어가보면 .aws/credential 파일에 acess key와 secret key 모두 잘 들어가 있고

심지어 aws s3 ls 명령도 잘 됐다 ㅠ

 

aws configure list 해보니까 잘 되어있음 ..

 

 

근데도 ec2에 올라간 spring 애플리케이션에서 s3 접속이 불가능하다고 하니.. 이상했다.

우선 IAM User Credential에 적용된 정책도 확인해보았으나 별 이상이 없었다.

 

 

그러던 중 누군가 이전에 동일한 이슈가 발생했었다고, 해서 들어보니..

 

aws configure로 credential 자체는 ec2-user 사용자로 설정이 되어있는데, 배포 하다보면 이 credential 정보를 ec2-user가 아닌 root로 하여금 찾게된다는 것이다.

aws sdk(java를 사용)는 로그에서 봤던 것처럼 credential 정보를 알아서 찾을 수 있는데 root로 하면 aws access key를 하던, ec2 IAM Role을 보던 제대로 된 권한을 가지고 있는 자격증명을 찾을 수 없어서 발생하는 이슈였다..

 

그래서 배포하여 서비스 시작할 때 -Daws.sharedCredentialsFile=/home/ec2-user/.aws/credentials 이 옵션을 추가하면 정상적으로 경로를 잘 찾아가게 된다는 것이다 ...

sudo nohup java -Dspring.profiles.active=dev -Daws.sharedCredentialsFile=/home/ec2-user/.aws/credentials -jar /home/ec2-user/deploy/test.jar \
      > /home/ec2-user/deploy/start.log" 2>&1 &

 

 

그렇게 했더니 잘 되었다!

여러 ec2에서 하나의 access key를 사용하는 건 상관 없었고,

EC2에 IAM Role과 Access key가 모두 들어가 있어서 문제였나? 싶었는데 문서를 확인해보니 credential 파일이 선순위고 ec2 iam role은 후순위였다

 

 

<자격 증명 설정 검색 순서>

  1. Java 시스템 속성
  2. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, 및 AWS_SESSION_TOKEN 환경 변수
  3. 웹 ID 토큰 및 IAM 역할 ARN
  4. 공유 credentials및 config파일
  5. Amazon ECS 컨테이너 자격 증명
  6. Amazon EC2 인스턴스 IAM 역할 제공 자격 증명
  7. SDK가 위에 나열된 모든 단계를 거쳐도 필요한 구성 설정을 찾을 수 없는 경우, 다음과 유사한 출력과 함께 예외가 발생합니다.

문서 참고 : https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials-chain.html#credentials-default

 

Default credentials provider chain in the AWS SDK for Java 2.x - AWS SDK for Java 2.x

Default credentials provider chain in the AWS SDK for Java 2.x The default credentials provider chain in the AWS SDK for Java 2.x automatically searches for AWS credentials in a predefined sequence of locations, allowing applications to authenticate with A

docs.aws.amazon.com

 

 

실제로 root로 전환해서 확인해보니 ec2-user와 다른 자격증명이 설정되어 있는 것을 볼 수 있었다.

심지어 .aws/credential 폴더와 파일조차도 없었음

여기에서 Type이 iam-role이라고 설정되어 있었는데 이게 바로 ec2에 부착된 iam role을 의미하는 거였다.. (iam role에는 s3 관련 권한이 존재하지 않았음 -> 당연히 S3 접근도 안되고 오류가 날 수 밖에 없었던 것)

 

ec2-user의 aws configure list에서 type 중 shared-credentials-file은 access key와 secret key를 의미하는 것이었다..

 

 

결론

: credential 이슈가 난다면

1. ~/.aws/credential 폴더에 [default]로 access key와 secret key가 있는지 확인

2. root와 ec2-user의 aws configure list 명령으로 어떤 credential 정보가 입력되어 있는지 확인

3. 애플리케이션 실행할 때 root인지 ec2-user인지 확인하기

 

가장 좋은 방법은 ec2 iam role을 쓰는 거지만.. 어쩔 수 없이 access key를 써야한다면 꼭 확인해보자

728x90