1. 문제발생
프로젝트 중 팀원 한 분의 실수로 Accesskey를 public 레포지토리에 그대로 업로드하는 일이 발생했다. 그 결과 AWS에서 해당 Accesskey로의 접근을 통제하였고, AWS 계정 사용에 큰 문제가 발생했다. 다행히 AWS에 지인이 있던 팀원분 덕에 AWS에서 제공하는 검증 절차대로 문제를 해결하였고, 하루 안에 AWS 계정에 걸린 락이 풀리게 되었다.
해당 문제는 Spring 코드 중에서 S3로 로그를 전송하기 위해 연동하는 코드를 개발용 레포에서는 .gitignore에 넣어주었지만 배포용 레포에는. gitignore안에 넣어주지 않았기에 발생한 문제였다. Accesskey를 흘리게 되면 코인 채굴과 같은 일에 수천만 원씩 클라우드 비용이 발생할 수 있기 때문에 아주 위험한 문제였고 우리는 혹시 모르는 사고를 막기 위해 프로젝트를 마치는 대로 계정을 삭제하였다.
2. 해결 방법
이러한 문제에 직면하지 않기 위해 필요했던것이 AWS IAM이다.
IAM이란 AWS Identity and Access Management로 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스이다.
IAM을 사용하면 사용자가 액세스할 수 있는 AWS 리소스를 제어하는 권한을 중앙에서 관리할 수 있다. IAM을 사용하여 리소스를 사용하도록 인증(로그인) 및 권한 부여(권한 있음)된 대상을 제어한다.
즉, IAM을 사용한다면 Spring 내의 자바 코드에서 accesskey를 직접 적어주지 않아도 되는 것이었다. 이제 코드를 통해 어떤 방식으로 spring에 IAM을 적용하는지 알아보자.
3. 예제
logController
- 해당 코드는 spring 내부의 Log 데이터를 S3로 전송하는 코드이다.
- 현재 날짜를 기준으로 파일을 만들어서 백엔드 단에서 로컬로 가지고 있는 상황에서 amazonS3Client 함수로 putobject를 실행시켜 데이터를 전송해 준다.
package com.project.backend.controller;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.project.backend.general.returnType.LogType;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
@RestController
@RequestMapping("/log")
@RequiredArgsConstructor
public class LogController {
private String S3Bucket = "standupseoul/raw/spring_logs"; // Bucket 이름
//
private final AmazonS3Client amazonS3Client;
@GetMapping("{datetime}")
public LogType updateLog(@PathVariable String datetime) throws Exception {
LogType logType = new LogType();
try{
String fileName = "/home/ubuntu/WebProject/StandUpSeoul_Back/backend/log/info/spring_" + datetime+".log";
File file = new File(fileName);
String saveName = "spring_" + datetime.replace("-","")+ ".log";
// S3에 업로드
amazonS3Client.putObject(
new PutObjectRequest(S3Bucket,saveName , file)
.withCannedAcl(CannedAccessControlList.PublicRead)
);
logType.setMessage("success");
return logType;
}catch (Exception e){
logType.setMessage("fail");
return logType;
}
}
}
awsConfig
- 아래 코드가 IAM을 사용하여 S3에 대한 권한을 spring EC2에 부여한 후 사용한 코드이다.
package com.project.backend.config;
import com.amazonaws.auth.InstanceProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AWSConfig {
@Bean
public AmazonS3Client amazonS3Client() {
InstanceProfileCredentialsProvider provider= new InstanceProfileCredentialsProvider(true);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withCredentials(provider)
.build();
}
}
build.gradle에 추가
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation 'software.amazon.awssdk:s3:2.17.41' // Amazon S3 SDK
implementation 'software.amazon.awssdk:sqs:2.16.0'
4. 참고자료
https://recordsoflife.tistory.com/1087
'AWS' 카테고리의 다른 글
AWS EC2인스턴스 VScode로 접속하여 Linux 환경에서 사용하기 (0) | 2023.06.28 |
---|