서론
기존에 Laravel을 이용하여 S3 파일업로드에 대하여 설명을 한 적이 있었습니다.
다만, 이때는 public으로 열어둔 S3에 손쉽게 업로드를 구현하는 방법을 설명 드렸었습니다.
하지만, 연습과 개인프로젝트에서는 상관없지만 실제 서비스 중인 프로젝트에서 위와 같이 구현하게 되면 보안상 이슈가 생기기 마련입니다..
이제, 위 방법에서 보안을 챙겨보도록 하겠습니다!
버킷 생성
먼저 AWS에서 버킷을 생성해 주도록 합니다.
리전은 서울을 선택하는 편이 아무래도 좋겠죠?
이외의 설정은 아래와 같이 설정해 주도록 합니다!
위와같이 S3 버킷을 생성한 후, IAM 설정을 이어서 해 보도록 하겠습니다.
IAM 설정
먼저, AWS에서 IAM 설정 페이지로 이동해 줍니다.
IAM>사용자로 들어가 주세요.
그 다음 우측 상단에 있는 [사용자 추가]버튼을 눌러서 서버에서 S3에 접근할 계정을 하나 생성해 줍니다.
사용자 이름은 본인이 구분하기 쉽도록 설정해 주시면 됩니다.
그 후, 다음 페이지에서 나오는 권한 설정에서 [기존 정책 직접 연결]을 선택, "S3"를 검색해 주신 후
AmazonS3FullAccess 권한을 체크해 준 뒤 사용자를 생성해 줍니다!
이후, 엑세스 키 ID와 SECRET ACCESS KEY를 확인하기 위하여 csv파일을 다운로드 해 주세요.
SECRET ACCESS KEY의 경우에는 다시 확인 할 수 없으니 해당 파일을 잘 보관해 주세요!
Laravel의 경우 해당 값들을 env파일에 적어 줍시다.
서울의 REGION값은 ap-northeast-2 입니다.
AWS_ENDPOINT는 버킷명을 제외한 S3의 주소값을 넣어주시면 됩니다.
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=ap-northeast-2
AWS_BUCKET=momo-storage
AWS_URL=http://[bucket-name].s3.ap-northeast-2.amazonaws.com
AWS_ENDPOINT=http://s3.ap-northeast-2.amazonaws.com
AWS_CLOUDFRONT_S3_URL=[cloud_frount_url]
이제, S3의 버킷 정책을 설정해보도록 하겠습니다.
아래 내용을 복사해 주셔서 사용해 주시면 편합니다.
S3 버킷 선택 -> 보안 -> 정책편집쪽을 확인해 주세요.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3::[bucket-name]",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"ec2 ip...",
"test pc ip",
"test pc2 ip"
]
}
}
}
]
}
[bucket-name]은 본인 S3의 버킷명을 넣어주시면 됩니다.
aws:SourceIp는 S3에 접근을 허용할 ip List를 넣어주세요.
실제 서비스가 돌아가는 서버의 IP와, 테스트로 사용할 개발 작업중인 로컬 PC의 IP를 추가해 주시면 될 것 같습니다.
그럼 위 경로를 통해서만 S3에 파일을 관리 할 수 있습니다.
CloudFront 설정
위와 같이 설정을 하게 된다면, S3의 url으로 업로드한 파일들을 확인 할 수 없게 됩니다.
CloudFront를 설정하여, S3 안에 있는 파일을 접근 할 수 있도록 구현해 줍시다.
AWS의 CloudFront Dashboard로 이동해 주신 뒤 [배포 생성]버튼을 클릭해 줍니다.
원본 도메인에서 S3 버킷을 선택해 주시고,
S3 버킷 엑세스의 [예, OAI 사용]을 선택해 줍니다.
새 OAI 생성 버튼을 눌러주시고,
버킷 정책 업데이트를 선택해 주세요!
이제, AWS의 보안 설정은 완료 되었습니다.
기존 포스트에서 Laravel을 통하여 기존에 파일 업로드를 구현 해 보았는데요, 소스코드에서 일부 변경을 해 주도록 합니다.
if($fileRequest::hasFile($uploadName)) {
$uploadFile = $fileRequest::file($uploadName);
if(is_array($uploadFile)) {
foreach($uploadFile as $file) {
$fileSize = $file->getSize(); // 파일 사이즈
$fileRealName = $file->getClientOriginalName(); // 원본 파일 명
$fileExtension = $file->getClientOriginalExtension(); // 확장자
$fileTempName = uniqid(); // 임시 파일 명
$filePath = $uploadFolderPath.'/'.$fileTempName.'.'.$fileExtension;
Storage::disk('s3')->put($filePath, file_get_contents($file));
array_push($uploadResult, array(
'file_size'=>$fileSize,
'file_real_name'=>$fileRealName,
'file_extension'=>$fileExtension,
'file_temp_name'=>$fileTempName,
'file_path'=>'/'.$filePath,
'file_s3_path'=>env('AWS_CLOUDFRONT_S3_URL').'/'.$filePath
));
}
} else {
$fileSize = $fileRequest::file($uploadName)->getSize(); // 파일 사이즈
$fileRealName = $fileRequest::file($uploadName)->getClientOriginalName(); // 원본 파일 명
$fileExtension = $fileRequest::file($uploadName)->getClientOriginalExtension(); // 확장자
$fileTempName = uniqid(); // 임시 파일 명
$filePath = $uploadFolderPath.'/'.$fileTempName.'.'.$fileExtension;
Storage::disk('s3')->put($filePath, file_get_contents($fileRequest::file($uploadName)));
array_push($uploadResult, array(
'file_size'=>$fileSize,
'file_real_name'=>$fileRealName,
'file_extension'=>$fileExtension,
'file_temp_name'=>$fileTempName,
'file_path'=>'/'.$filePath,
'file_s3_path'=>env('AWS_CLOUDFRONT_S3_URL').'/'.$filePath
));
}
return $uploadResult;
}
기존 코드에서, 파일 업로드 시 public 권한을 주는 부분만 제거 하였습니다.
자세한 설명은 서론에 포함된 링크를 확인해 주세요!
위를 테스트 진행해보면
위와 같이 업로드 됨을 확인 할 수 있습니다.
파일 확인은 cloudfront에서 배포한 url값을 이용하여 확인해 주도록 합니다!
'Programming' 카테고리의 다른 글
laravel.log could not be opened in append mode: failed to o pen stream: Permission denied (0) | 2022.05.03 |
---|---|
Laravel + Firebase 연동 및 앱 버전 관리 (0) | 2022.04.29 |
npm install시 npm ERR! code ERESOLVE 오류 해결 (0) | 2022.04.21 |
CKEditor5 - Web Editor CKEditor5 이미지 업로드(For jQuery) (5) | 2022.04.15 |
[Javascript] mobile touch Event (1) | 2020.12.28 |