본문 바로가기
프로젝트/Recipository

[Dev] 23.04.08. AWS S3 Bucket으로의 업로드를 위한 IAM 역할 연결

by 규글 2023. 4. 8.

Access Key 대신 권장하고 있는 대안

 현재 S3로의 업로드에는 properties에 입력한 IAM 계정의 access key와 secret key를 활용하여 AmazonS3Client 객체를 생성하고 있다. 하지만 IAM의 access key를 생성하는 과정에서 Amazon은 그 대신 위 메시지를 보이며 EC2 인스턴스에 IAM 역할을 할당하여 액세스를 위한 임시 보안 인증을 자동으로 제공하는 방식을 권장하고 있다.

 보이는 Learn more를 눌러 열리는 페이지에서 어떤 방식으로 작업해야할 지 알 수 있다.[각주:1]

 

 EC2 인스턴스 내에서 직접 AWS 보안 인증 정보를 저장하고, 그것을 인스턴스의 어플리케이션에서 사용하는 것을 허용한 것이 바로 access key와 secret key이다. 하지만 이 인증 정보에 대한 업데이트를 필요로 할 때, 사실상 추가적인 작업을 요하는 것이라고 할 수 있다.

 그래서 AWS에서는 IAM 역할을 사용하여 EC2 인스턴스에서 실행되는 어플리케이션에 대한 임시 보안 인증 정보를 관리하는 방식을 택해야한다고 권하고 있다. 이 방식을 택하면 장기 보안 인증 정보인 access key를 함께 배포하지 않아도 된다고 언급한다. 대신 필요한 절차가 있는데, 그것은 '인스턴스 프로파일'을 생성하는 것이다. 후에 다시 언급하겠지만, 이 인스턴스 프로파일은 IAM 역할을 생성하면서 자동으로 생성된다.

 결론적으로 이 역할 자격 증명은 임시적이고 자동으로 교체되기 때문에 따로 관리하지 않아도 되면서도 장기적인 보안 위험을 걱정하지 않아도 되는 장점이 있으므로 access key를 생성할 때 다른 방식을 권장했다고 할 수 있다.

 

 동일한 페이지에서 EC2 인스턴스의 역할을 다음과 같이 설명하고 있다.

  1. 관리자가 IAM을 사용하여 역할을 생성한다. 예시 이미지의 경우는 S3의 photos bucket에 access 하는 권한을 부여한 것이다.
  2. 개발자가 인스턴스를 시작하고, 해당 인스턴스에 생성한 역할을 부여한다.
  3. EC2 인스턴스에서 어플리케이션이 실행되면 EC2 인스턴스 메타 데이터에서 임시 보안 자격 증명을 가져와서 역할을 나타낸다.
  4. 어플리케이션은 이 임시 보안 자격 증명을 통해서 bucket에 액세스 한다.

 

 이렇게 인스턴스를 생성하고, 역할을 부여하는 것에 있어서 계정에는 권한이 필요하다고 한다. 물론 필자의 경우는 필자의 계정으로 모두 관리하고 있으므로 상관이 없으나, 타 AWS 계정이나 IAM 계정에게 권한을 부여하고 해당 계정으로 인스턴스를 생성하고 역할을 부여하고자 한다면 그에 맞는 권한을 정책으로 설정해주어야 한다. (현재 참고하고 있는 docs 게시글에서는 우리말로 '시작'이라고 표현하고 있으나 영문으로는 'Launch'로 표현하고 있으며, 이는 새롭게 인스턴스를 생성하는 '인스턴스 시작'을 의미한다. 중지된 인스턴스를 시작하는 것은 'Start'이다. 필자가 삽질했다는 것은 비밀이 아니다.) 필요하면 참고하도록 하며, 인스턴스를 생성하면서 역할을 부여하는 것 또한 docs에서 설명하고 있다.[각주:2]

 

 해당 docs에서는 인스턴스 프로파일도 설명하고 있다. EC2에서는 인스턴스 프로파일을 IAM 역할의 컨테이너로 사용되며, IAM console을 사용하여 역할을 생성한 경우에는 인스턴스 프로파일이 자동으로 생성된다고 한다.

 

 

IAM 역할 생성과 인스턴스 프로파일 생성

 원래 읽고 있던 docs를 아래로 내리면 Java를 사용한 역할 구성 페이지로 안내해준다. 페이지로 이동해보자.[각주:3]

 

 역시 EC2 인스턴스 내에 access key를 직접 저장할 때 권장하는 방법이라고 언급하면서, 인스턴스 프로파일에는 역할이 포함되어 있어서 EC2 인스턴스에서 실행되는 프로그램이 임시 자격 증명을 얻을 수 있다고 말한다. EC2 인스턴스에 역할을 할당하면, 인스턴스 프로파일이 자동으로 생성된다는 말과 통하며, 그 역할을 어플리케이션에 전달하여 임시 자격 증명을 얻는 방식인 것 같다.

 

S3Client s3 = S3Client.builder()
       .credentialsProvider(InstanceProfileCredentialsProvider.builder().build())
       .build();

 설명을 조금 내려보면 어떤 방식을 취해야하는지 설명하고 있다. 위와 같은 코드를 작성하여 Bean으로 만들면 임시 자격 증명을 얻을 수 있는 것 같다. 중요한 것은 이 방식을 EC2 인스턴스에서 실행되는 어플리케이션에서만 사용할 수 있다는 점이다.

 

AwsS3Config.java

    @Bean
    public AmazonS3Client amazonS3Client(){
//        BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);

//        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
//                .withRegion(region)
//                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
//                .build();

        InstanceProfileCredentialsProvider provider = InstanceProfileCredentialsProvider.getInstance();
        
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(provider)
                .build();
    }

 필자의 경우는 S3Client가 없어서 기존에 작성해두었던 AmaxonS3ClientBuilder을 그대로 활용했다. 변화가 있다면 기존에 BasicAWSCredentials 대신 docs의 InstanceProfileCredentialsProvider를 활용했다는 점이다.

 

 그렇다면 이때 어떤 역할을 전달해주어야 할까?

 

 Docs를 조금 더 내리면 친절하게 설명되어 있는데, 순서대로 따라가보도록 하겠다.

 

 가장 먼저 AWS에 로그인하여 IAM 서비스역할 탭에 들어가서 '역할 만들기'를 누른다.

 

 신뢰할 수 있는 엔티티 선택에서 유형은 AWS 서비스, 사용 사례는 EC2를 선택한다. 필자는 EC2 인스턴스에 올린 사항에 대한 작업을 하고 싶기 때문에 선택한 것이다.

 

 다음은 권한을 추가해준다. 'S3'를 검색하여 AmazonS3FullAccess를 찾아 선택했다. 이는 S3 Bucket을 처음 생성할 당시 IAM 계정을 만들면서 해당 계정에 권한을 추가했던 바로 그것과 동일하다.[각주:4] 필자는 역할을 부여하여 S3 Bucket에 이미지를 업로드하는 것이 목적이기 때문에 선택해주었다. 그런데 S3에 대한 full access 권한을 주는 것은 조금 부담스럽다. 그래서 바로 하단에 보이는 권한 경계 설정 부분을 열어보았다.

 

 권한에 대한 경계를 설정해줄 수 있었는데, 정책 생성을 통해서 S3 Bucket에 작성했던 정책의 내용을 작성하여 추가해주고, 해당 항목을 권한 경계로 선택했다. 

 

 역할에 대한 이름까지 입력해주고 역할 생성을 마무리해주면 되겠다.

 

 이제 생성한 역할을 EC2 서비스의 인스턴스 > 작업 > 보안 > IAM 역할 수정 에서 역할을 연결해준다.

 

 

실제 동작

com.amazonaws.SdkClientException: Failed to connect to service endpoint:

 로컬에서는 업로드가 온전하게 동작하지 않으면서 오류 메시지도 console에서 확인할 수 없었고, 따로 break point를 걸어 확인하여 위와 같은 메시지를 확인하게 되었다. 당연히 오류가 발생하는 것이, 로컬은 EC2 인스턴스가 아니기 때문에 어플리케이션이 정상적으로 동작하지 않는 것이다.

 

 이를 다시금 build 하여 EC2 인스턴스에 jar file을 copy한 뒤, 인스턴스에서 어플리케이션을 실행하여 동작하도록 해보면 목적대로 정상적인 동작을 확인할 수 있었다.

 

 

 이렇게 EC2 인스턴스에 IAM 역할을 연결하고, 이를 통해서 access key와 secret key를 활용하지 않고도 S3 Bucket에 이미지를 업로드하는 작업까지 시도해보았다. 이제 남은 것은 EC2 인스턴스와 github를 연동하여 배포하는 방식에 대해 알아보도록 하자.

 

Reference

댓글