IAM 역할(Role)을 사용해서 ec2에 S3 권한주기

hongo·2023년 12월 21일
1

IAM 사용자 key를 사용한 방법 VS IAM 역할을 사용한 방법

현재 spring boot 프로젝트에서 S3에 이미지를 업로드하는 기능이 존재한다. S3에 접근하려면 aws IAM 사용자(User)의 accesskey와 secretkey가 필요하다. 보통 application.yml에 accesskey와 secretkey를 추가하여 s3Client객체를 생성한다.

하지만 ec2를 사용중이라면, S3 접근 권한이 있는 IAM 역할을 생성하여 해당 ec2에 적용할 수 있다. 이 경우 application.yml에 accesskey와 secretkey정보를 입력하지 않고 지역 정보만 가지고 s3Client객체를 생성해두면, 해당 ec2에서 자동으로 key정보를 가지고 S3에 접근할 수 있다.

IAM 사용자의 key를 사용한 S3 접근 방법과 IAM 역할을 사용한 S3 접근 방법은 어떤 차이가 있을까?

  • 일단 위에서 언급했듯이 IAM 사용자는 프로퍼티 파일에 key정보를 입력해줘야하고, IAM 역할은 key정보를 입력하지 않아도 지정한 ec2에서 자동으로 인증을 수행한다.
  • aws 문서 를 보면 IAM 역할은 임시 자격 증명(temporary credentials)을 사용한다. IAM 역할은 최대 세션 지속 시간을 가지고 있는데, 최소 1시간(디폴트) ~ 최대 12시간까지 설정이 가능하다. 이 시간이 지나면 자동으로 IAM 역할을 재생성한다. (IAM 역할 세션 문서 참고) IAM 사용자의 key는 일시적인 자격이 아니라 장기적인 자격이므로 key를 주기적으로 재발급해주지 않는 이상 보안상 더 불리하다.

결론적으로 IAM 역할을 사용한 방식이 더 보안이 뛰어나고, 관리해야하는 범위가 적다고 느껴졌기에 IAM 역할을 사용해서 S3 접근 권한을 구성했다.

IAM 역할을 사용해서 ec2에 S3 권한주기

이제 본격적으로 권한을 줘보자!

s3 bucket 생성

퍼블릭 엑세스를 차단한 버킷 하나를 생성했다. 버킷의 이름은 hanglog-image로 지정했다.

IAM 정책 생성

IAM 역할이 가지고 있는 정책을 생성해줘야한다. AWS 콘솔에서 IAM -> 정책 으로 들어가 새 정책을 생성해준다. (디폴트로 s3 풀 엑세스같은 정책이 여러 개 생성되어있긴한다. 이걸 사용해도 무방하지만, 풀 엑세스까진 필요가 없어서 새로 만들었다.)

  • S3 접근 권한을 주고싶었기에 S3를 선택한다.
  • S3 작업 중, GetObject, PutObject등 내가 사용하고 싶은 권한을 추가한다.

  • 선택한 작업을 바탕으로 필요한 리소스들이 항목에 뜬다. ARN 추가를 클릭해서 ARN 정보를 입력해줘야한다. (ARN(Amazon Resource Name) : 리소스를 고유하게 식별하는 이름)

  • object의 경우 s3 버킷의 이름을 등록한다. 모든 object에 대한 get, put 권한을 주고싶으므로 모든 object name을 체크했다.

다음을 눌러 정책의 이름을 지정하고 생성한다. 정책의 이름은 s3_policy로 지정했다.

IAM 역할 생성

AWS 콘솔에서 IAM -> 역할 로 들어가 새 역할을 생성해준다.

  • 사용 사례는 EC2를 지정해주었다.

  • 위에서 생성한 정책을 등록한다.

다음을 눌러 역할의 이름을 지정하고 생성한다.

ec2에 IAM 역할 지정

IAM 역할의 정책을 적용하고 싶은 ec2 인스턴스에 들어가 작업 -> 보안 -> IAM 역할 수정 페이지로 들어간다.
위에서 생성한 역할을 선택해 등록한다.

Spring boot에서 s3Client 생성

이제 ec2에 빌드될 spring boot application에서 s3Client를 생성해서 S3에 업로드하는 로직을 작성하면, ec2에 배포가 되었을 때 자동으로 IAM 역할을 사용해 S3에 접근할 수 있다.

아래는 예시 코드이다.

@Configuration
public class S3Config {

    @Value("${cloud.aws.region.static}")
    private String region;

    @Bean
    public AmazonS3 S3Client() {
        return AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .build();
    }
}
@Component
@RequiredArgsConstructor
public class ImageUploader {

    private static final String CACHE_CONTROL_VALUE = "max-age=3153600";

    private final AmazonS3 s3Client;

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    @Value("${cloud.aws.s3.folder}")
    private String folder;

    public List<String> uploadImages(final List<ImageFile> imageFiles) {
        return imageFiles.stream()
                .map(this::uploadImage)
                .toList();
    }

    private String uploadImage(final ImageFile imageFile) {
        final String path = folder + imageFile.getHashedName();
        final ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(imageFile.getContentType());
        metadata.setContentLength(imageFile.getSize());
        metadata.setCacheControl(CACHE_CONTROL_VALUE);

        try (final InputStream inputStream = imageFile.getInputStream()) {
            s3Client.putObject(bucket, path, inputStream, metadata);
        } catch (final AmazonServiceException e) {
            throw new ImageException(INVALID_IMAGE_PATH);
        } catch (final IOException e) {
            throw new ImageException(INVALID_IMAGE);
        }
        return imageFile.getHashedName();
    }
}

부록 - IAM 정책이 제대로 생성되었는지 테스트

해당 페이지에 접속해 IAM 정책을 테스트 할 수 있다.


테스트하고싶은 정책을 선택한 후, 테스트하고 싶은 작업을 선택해 테스트용 리소스를 등록해주면 된다. (PutObject의 경우 버킷의 최상단 루트 arn을 등록, GetObject의 경우 테스트용 object를 미리 업로드하고 해당 object의 arn을 등록해주었다.)

부록 - ec2에서 S3 접근이 잘 되는지 테스트

awscli를 사용해 ec2에서 S3에 접근이 잘 되는지 확인해볼 수 있다.

sudo apt install awscli

예시 - putObject 테스트

aws s3 cp {업로드할 object 경로} s3://{업로드할 S3 버킷의 폴더}
aws s3 cp ./test.jpeg s3://hanglog-image/
profile
https://github.com/hgo641

2개의 댓글

comment-user-thumbnail
2024년 9월 9일

많은 도움 받았습니다. 감사합니다.

1개의 답글