현재 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 역할을 사용한 방식이 더 보안이 뛰어나고, 관리해야하는 범위가 적다고 느껴졌기에 IAM 역할을 사용해서 S3 접근 권한을 구성했다.
이제 본격적으로 권한을 줘보자!
퍼블릭 엑세스를 차단한 버킷 하나를 생성했다. 버킷의 이름은 hanglog-image로 지정했다.
IAM 역할이 가지고 있는 정책을 생성해줘야한다. AWS 콘솔에서 IAM -> 정책 으로 들어가 새 정책을 생성해준다. (디폴트로 s3 풀 엑세스같은 정책이 여러 개 생성되어있긴한다. 이걸 사용해도 무방하지만, 풀 엑세스까진 필요가 없어서 새로 만들었다.)



다음을 눌러 정책의 이름을 지정하고 생성한다. 정책의 이름은 s3_policy로 지정했다.
AWS 콘솔에서 IAM -> 역할 로 들어가 새 역할을 생성해준다.


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

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

테스트하고싶은 정책을 선택한 후, 테스트하고 싶은 작업을 선택해 테스트용 리소스를 등록해주면 된다. (PutObject의 경우 버킷의 최상단 루트 arn을 등록, GetObject의 경우 테스트용 object를 미리 업로드하고 해당 object의 arn을 등록해주었다.)
awscli를 사용해 ec2에서 S3에 접근이 잘 되는지 확인해볼 수 있다.
sudo apt install awscli
예시 - putObject 테스트
aws s3 cp {업로드할 object 경로} s3://{업로드할 S3 버킷의 폴더}
aws s3 cp ./test.jpeg s3://hanglog-image/
많은 도움 받았습니다. 감사합니다.