서버 측 코드없이 JavaScript 만 사용하여 REST API를 통해 클라이언트 시스템에서 Amazon S3로 직접 파일 업로드를 구현하고 있습니다. 모든 것이 잘 작동하지만 한 가지 걱정이됩니다 …
Amazon S3 REST API에 요청을 보낼 때 요청에 서명하고 서명을 Authentication
헤더에 넣어야합니다 . 서명을 만들려면 비밀 키를 사용해야합니다. 그러나 모든 것은 클라이언트 측에서 발생하므로 비밀 키는 페이지 소스에서 쉽게 공개 할 수 있습니다 (소스를 난독 화 / 암호화하더라도).
어떻게 처리 할 수 있습니까? 그리고 전혀 문제가 있습니까? 어쩌면 특정 개인 키 사용을 특정 CORS Origin의 REST API 호출 및 PUT 및 POST 메소드로만 제한하거나 키를 S3 및 특정 버킷으로 만 링크 할 수 있습니까? 다른 인증 방법이있을 수 있습니까?
“서버리스”솔루션이 이상적이지만 파일을 서버에 업로드 한 다음 S3로 전송하는 것을 제외하고 일부 서버 측 처리를 고려할 수 있습니다.
답변
POST를 사용하는 브라우저 기반 업로드가 원하는 것 같습니다.
기본적으로 서버 측 코드가 필요하지만 서명 된 정책 만 생성하면됩니다. 클라이언트 측 코드에 서명 된 정책이 있으면 데이터가 서버를 통하지 않고 POST를 사용하여 S3에 직접 업로드 할 수 있습니다.
공식 문서 링크는 다음과 같습니다.
다이어그램 : http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html
예제 코드 : http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTExamples.html
서명 된 정책은 다음과 같은 형식으로 html로 작성됩니다.
<html>
<head>
...
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
...
</head>
<body>
...
<form action="http://johnsmith.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
Key to upload: <input type="input" name="key" value="user/eric/" /><br />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="success_action_redirect" value="http://johnsmith.s3.amazonaws.com/successful_upload.html" />
Content-Type: <input type="input" name="Content-Type" value="image/jpeg" /><br />
<input type="hidden" name="x-amz-meta-uuid" value="14365123651274" />
Tags for File: <input type="input" name="x-amz-meta-tag" value="" /><br />
<input type="hidden" name="AWSAccessKeyId" value="AKIAIOSFODNN7EXAMPLE" />
<input type="hidden" name="Policy" value="POLICY" />
<input type="hidden" name="Signature" value="SIGNATURE" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
...
</html>
FORM 조치는 파일 을 서버가 아닌 S3으로 직접 전송 합니다.
사용자 중 한 명이 파일을 업로드하려고 할 때마다 POLICY
및 SIGNATURE
서버에 파일을 작성 합니다. 페이지를 사용자 브라우저로 되돌립니다. 그런 다음 사용자는 서버를 통하지 않고 파일을 S3에 직접 업로드 할 수 있습니다.
정책에 서명하면 일반적으로 몇 분 후에 정책이 만료됩니다. 이렇게하면 사용자가 업로드하기 전에 서버와 대화해야합니다. 원하는 경우 업로드를 모니터링하고 제한 할 수 있습니다.
서버와주고받는 유일한 데이터는 서명 된 URL입니다. 비밀 키는 서버에서 비밀로 유지됩니다.
답변
AWS S3 Cognito가이 링크를 시도하면됩니다.
http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-examples.html#Amazon_S3
이 코드를 사용해보십시오
리전, IdentityPoolId 및 버킷 이름 만 변경하면됩니다.
<!DOCTYPE html>
<html>
<head>
<title>AWS S3 File Upload</title>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js"></script>
</head>
<body>
<input type="file" id="file-chooser" />
<button id="upload-button">Upload to S3</button>
<div id="results"></div>
<script type="text/javascript">
AWS.config.region = 'your-region'; // 1. Enter your region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'your-IdentityPoolId' // 2. Enter your identity pool
});
AWS.config.credentials.get(function(err) {
if (err) alert(err);
console.log(AWS.config.credentials);
});
var bucketName = 'your-bucket'; // Enter your bucket name
var bucket = new AWS.S3({
params: {
Bucket: bucketName
}
});
var fileChooser = document.getElementById('file-chooser');
var button = document.getElementById('upload-button');
var results = document.getElementById('results');
button.addEventListener('click', function() {
var file = fileChooser.files[0];
if (file) {
results.innerHTML = '';
var objKey = 'testing/' + file.name;
var params = {
Key: objKey,
ContentType: file.type,
Body: file,
ACL: 'public-read'
};
bucket.putObject(params, function(err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
listObjs();
}
});
} else {
results.innerHTML = 'Nothing to upload.';
}
}, false);
function listObjs() {
var prefix = 'testing';
bucket.listObjects({
Prefix: prefix
}, function(err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
var objKeys = "";
data.Contents.forEach(function(obj) {
objKeys += obj.Key + "<br>";
});
results.innerHTML = objKeys;
}
});
}
</script>
</body>
</html>
자세한 내용은 Github을 확인하십시오.
답변
“서버리스”솔루션을 원한다고 말하고 있습니다. 그러나 이는 “귀하의”코드를 루프에 넣을 수있는 능력이 없다는 것을 의미합니다. (참고 : 일단 코드를 클라이언트에 제공하면 코드는 “그들의”코드입니다.) CORS를 잠그면 도움이되지 않습니다. 사람들은 웹 기반이 아닌 도구 (또는 웹 기반 프록시)를 쉽게 작성할 수 있습니다 올바른 CORS 헤더가 시스템을 남용합니다.
가장 큰 문제는 다른 사용자를 구별 할 수 없다는 것입니다. 한 사용자가 자신의 파일을 나열 / 액세스하도록 허용 할 수는 없지만 다른 사용자가 파일을 액세스하지 못하게합니다. 악용을 감지하면 키 변경을 제외하고는 할 수있는 일이 없습니다. (공격자는 아마도 다시 도착할 수 있습니다.)
최선의 방법은 자바 스크립트 클라이언트 용 키를 사용하여 “IAM 사용자”를 만드는 것입니다. 하나의 버킷에만 쓰기 권한을 부여하십시오. (그러나 이상적으로는 ListBucket 작업을 활성화하지 마십시오. 공격자에게 더 매력적입니다.)
서버가있는 경우 (월간 $ 20의 간단한 마이크로 인스턴스도) 실시간으로 남용을 모니터링 / 예방하면서 서버의 키에 서명 할 수 있습니다. 서버가 없으면 최선을 다해 사후 악용 사례를 정기적으로 모니터링하는 것이 가장 좋습니다. 내가 할 일은 다음과 같습니다.
1) 해당 IAM 사용자의 키를 주기적으로 교체합니다. 매일 밤 해당 IAM 사용자의 새 키를 생성하고 가장 오래된 키를 바꿉니다. 2 개의 키가 있으므로 각 키는 2 일 동안 유효합니다.
2) S3 로깅을 활성화하고 매시간 로그를 다운로드하십시오. “너무 많은 업로드”및 “너무 많은 다운로드”에 대해 경고를 설정하십시오. 총 파일 크기와 업로드 된 파일 수를 모두 확인하려고합니다. 또한 전체 총계와 IP 주소 당 총계 (임계 값이 낮은)를 모두 모니터링하려고합니다.
이러한 검사는 데스크탑에서 실행할 수 있으므로 “서버리스”로 수행 할 수 있습니다. (즉, S3는 모든 작업을 수행합니다. 이러한 프로세스는 S3 버킷 남용을 경고하기 위해 해당 월말에 대규모 AWS 요금을 받지 않습니다 .)
답변
허용 된 답변에 더 많은 정보를 추가하면 AWS 서명 버전 4를 사용하여 실행중인 코드 버전을 확인하기 위해 내 블로그를 참조 할 수 있습니다.
여기에 요약됩니다 :
사용자가 업로드 할 파일을 선택하자마자 다음을 수행하십시오. 1. 웹 서버를 호출하여 필요한 매개 변수를 생성하는 서비스를 시작하십시오.
-
이 서비스에서 AWS IAM 서비스를 호출하여 임시 자격 증명을 받으십시오.
-
cred가 있으면 버킷 정책 (기본 64 인코딩 문자열)을 생성하십시오. 그런 다음 임시 비밀 액세스 키로 버킷 정책에 서명하여 최종 서명을 생성하십시오.
-
필요한 매개 변수를 UI로 다시 전송
-
이것이 수신되면 html 양식 오브젝트를 작성하고 필수 매개 변수를 설정 한 후 POST하십시오.
자세한 내용은 https://wordpress1763.wordpress.com/2016/10/03/browser-based-upload-aws-signature-version-4/ 를 참조
하십시오.
답변
서명을 만들려면 비밀 키를 사용해야합니다. 그러나 모든 것은 클라이언트 측에서 발생하므로 비밀 키는 페이지 소스에서 쉽게 공개 할 수 있습니다 (소스를 난독 화 / 암호화하더라도).
이곳은 당신이 오해 한 곳입니다. 디지털 서명을 사용하는 이유는 비밀 키를 밝히지 않고 올바른 것을 확인할 수 있기 때문입니다. 이 경우 사용자가 양식 게시에 설정 한 정책을 수정하지 못하도록 디지털 서명이 사용됩니다.
여기에있는 것과 같은 디지털 서명은 웹 전체의 보안에 사용됩니다. 누군가 (NSA?)가 실제로 그들을 깨뜨릴 수 있다면 S3 버킷보다 훨씬 큰 목표를 가질 것입니다 🙂
답변
Javascript 브라우저에서 AWS S3로 파일을 업로드하고 S3 버킷의 모든 파일을 나열하는 간단한 코드를 제공했습니다.
단계 :
-
IdentityPoolId 생성 방법을 이해하려면 http://docs.aws.amazon.com/cognito/latest/developerguide/identity-pools.html
-
S3의 콘솔 페이지로 이동하여 버킷 속성에서 cors 구성을 열고 다음 XML 코드를 작성하십시오.
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedMethod>HEAD</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>
-
다음 코드가 포함 된 HTML 파일을 만들어 자격 증명을 변경하고 브라우저에서 파일을 열고 즐기십시오.
<script type="text/javascript"> AWS.config.region = 'ap-north-1'; // Region AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'ap-north-1:*****-*****', }); var bucket = new AWS.S3({ params: { Bucket: 'MyBucket' } }); var fileChooser = document.getElementById('file-chooser'); var button = document.getElementById('upload-button'); var results = document.getElementById('results'); function upload() { var file = fileChooser.files[0]; console.log(file.name); if (file) { results.innerHTML = ''; var params = { Key: n + '.pdf', ContentType: file.type, Body: file }; bucket.upload(params, function(err, data) { results.innerHTML = err ? 'ERROR!' : 'UPLOADED.'; }); } else { results.innerHTML = 'Nothing to upload.'; } } </script> <body> <input type="file" id="file-chooser" /> <input type="button" onclick="upload()" value="Upload to S3"> <div id="results"></div> </body>
-
답변
서버 측 코드가없는 경우 보안은 클라이언트 측에서 JavaScript 코드에 대한 액세스 보안에 의존합니다 (예 : 코드를 가진 모든 사용자가 무언가를 업로드 할 수 있음).
따라서 공개 쓰기 가능하지만 읽을 수없는 특수 S3 버킷을 만드는 것이 좋습니다. 따라서 클라이언트 측에 서명 된 구성 요소가 필요하지 않습니다.
버킷 이름 (예 : GUID)은 악의적 인 업로드에 대한 유일한 방어 수단이지만 잠재적 인 공격자는 버킷 만 쓸 수 있기 때문에 버킷을 사용하여 데이터를 전송할 수 없습니다.
