Lambda関数でS3 AWSサービスからアクセス拒否エラーが発生しています。
これはコードです:
// dependencies
var async = require('async');
var AWS = require('aws-sdk');
var gm = require('gm').subClass({ imageMagick: true }); // Enable ImageMagick integration.
exports.handler = function(event, context) {
var srcBucket = event.Records[0].s3.bucket.name;
// Object key may have spaces or unicode non-ASCII characters.
var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
/*
{
originalFilename: <string>,
versions: [
{
size: <number>,
crop: [x,y],
max: [x, y],
rotate: <number>
}
]
}*/
var fileInfo;
var dstBucket = "xmovo.transformedimages.develop";
try {
//TODO: Decompress and decode the returned value
fileInfo = JSON.parse(key);
//download s3File
// get reference to S3 client
var s3 = new AWS.S3();
// Download the image from S3 into a buffer.
s3.getObject({
Bucket: srcBucket,
Key: key
},
function (err, response) {
if (err) {
console.log("Error getting from s3: >>> " + err + "::: Bucket-Key >>>" + srcBucket + "-" + key + ":::Principal>>>" + event.Records[0].userIdentity.principalId, err.stack);
return;
}
// Infer the image type.
var img = gm(response.Body);
var imageType = null;
img.identify(function (err, data) {
if (err) {
console.log("Error image type: >>> " + err);
deleteFromS3(srcBucket, key);
return;
}
imageType = data.format;
//foreach of the versions requested
async.each(fileInfo.versions, function (currentVersion, callback) {
//apply transform
async.waterfall([async.apply(transform, response, currentVersion), uploadToS3, callback]);
}, function (err) {
if (err) console.log("Error on excecution of watefall: >>> " + err);
else {
//when all done then delete the original image from srcBucket
deleteFromS3(srcBucket, key);
}
});
});
});
}
catch (ex){
context.fail("exception through: " + ex);
deleteFromS3(srcBucket, key);
return;
}
function transform(response, version, callback){
var imageProcess = gm(response.Body);
if (version.rotate!=0) imageProcess = imageProcess.rotate("black",version.rotate);
if(version.size!=null) {
if (version.crop != null) {
//crop the image from the coordinates
imageProcess=imageProcess.crop(version.size[0], version.size[1], version.crop[0], version.crop[1]);
}
else {
//find the bigger and resize proportioned the other dimension
var widthIsMax = version.size[0]>version.size[1];
var maxValue = Math.max(version.size[0],version.size[1]);
imageProcess=(widthIsMax)?imageProcess.resize(maxValue):imageProcess.resize(null, maxValue);
}
}
//finally convert the image to jpg 90%
imageProcess.toBuffer("jpg",{quality:90}, function(err, buffer){
if (err) callback(err);
callback(null, version, "image/jpeg", buffer);
});
}
function deleteFromS3(bucket, filename){
s3.deleteObject({
Bucket: bucket,
Key: filename
});
}
function uploadToS3(version, contentType, data, callback) {
// Stream the transformed image to a different S3 bucket.
var dstKey = fileInfo.originalFilename + "_" + version.size + ".jpg";
s3.putObject({
Bucket: dstBucket,
Key: dstKey,
Body: data,
ContentType: contentType
}, callback);
}
};
これはCloudwatchのエラーです。
AccessDenied: Access Denied
これはスタックエラーです。
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/services/s3.js:329:35)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:596:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:21:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:37:9)
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:598:12)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
S3バケットに関する他の説明や情報がない場合、すべてのユーザーがリストを作成して削除できます。
S3バケットにアクセスするにはどうすればよいですか?
PS:Lambdaイベントプロパティでは、プリンシパルは正しく、管理者権限を持っています。
私はこの問題に出くわし、IAMポリシーが何時間も狂った後、解決策は次のとおりでした。
できた慎重に作成されたIAMロールポリシーは重要ではなく、特定のバケットポリシーも重要ではありません(機能させるためにそれらも作成しました)。または、私のアカウントでは機能しません。
[編集]
多くの調整を行った後、上記のアプローチは最適ではありません。これを試して:
{ "Version": "2012-10-17", "Id": "Lambda access bucket policy", "Statement": [ { "Sid": "All on objects in bucket lambda", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::AWSACCOUNTID:root" }, "Action": "s3:*", "Resource": "arn:aws:s3:::BUCKET-NAME/*" }, { "Sid": "All on bucket by lambda", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::AWSACCOUNTID:root" }, "Action": "s3:*", "Resource": "arn:aws:s3:::BUCKET-NAME" } ] }
私のために働いたので、認証されたすべてのAWSユーザーと共有する必要はありません(ほとんどの場合、理想的ではありません)。
興味深いことに、ファイルが存在しない場合、AWSは403(アクセス拒否)を返します。ターゲットファイルがS3バケットにあることを確認してください。
Resourceを指定する場合は、サブフォルダーの指定も忘れずに追加してください。このような:
"Resource": [
"arn:aws:s3:::BUCKET-NAME",
"arn:aws:s3:::BUCKET-NAME/*"
]
私もこの問題に遭遇しました。s3:GetObject*
は、そのオブジェクトのバージョンを取得しようとしているACL内にあります。
S3バケットに暗号化を設定している場合(AWS KMSなど)、Lambda関数に適用されたIAMロールがIAM>暗号化キー> region> key>キーユーザーS3バケットを保存中に暗号化するために使用した対応するキー。
たとえば、スクリーンショットでは、Lambda関数にIAMのKey Userとして適用したCyclopsApplicationLambdaRoleロールを追加しましたS3バケットの暗号化に使用したのと同じAWS KMSキーに対して。 Encryption keysUIを開くときに、キーの正しい領域を選択することを忘れないでください。
S3バケットに暗号化を追加するために使用したキーを見つけます:
基本的な設計図を実行しようとしましたPython lambda関数[コード例])同じ問題がありました。実行ロールはlambda_basic_execution
S3>(ここに自分のバケット名)> permissionsに行きました。
私は初心者なので、JSONを自分で記述するのではなく、Amazonが提供するPolicy Generatorを使用しました: http://awspolicygen.s3。 amazonaws.com/policygen.html 私のJSONは次のようになります。
{
"Id": "Policy153536723xxxx",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt153536722xxxx",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::tokabucket/*",
"Principal": {
"AWS": [
"arn:aws:iam::82557712xxxx:role/lambda_basic_execution"
]
}
}
]
そして、コードはうまく実行されました:
他のすべてのポリシーアヒルが並んでいる場合、オブジェクトが存在せず、要求者がバケットに対するListObjects権限を持っていない場合、S3は引き続きアクセス拒否メッセージを返します。
から https://docs.aws.Amazon.com/AmazonS3/latest/API/RESTObjectGET.html :
...リクエストしたオブジェクトが存在しない場合、Amazon S3が返すエラーは、s3:ListBucketアクセス許可も持っているかどうかによって異なります。
バケットに対するs3:ListBucketアクセス許可がある場合、Amazon S3はHTTPステータスコード404( "no such key")エラーを返します。 s3:ListBucketアクセス許可がない場合、Amazon S3はHTTPステータスコード403(「アクセス拒否」)エラーを返します。
私はこの問題に何時間も苦労していました。私はAmazonS3EncryptionClientを使用していましたが、何も助けませんでした。次に、クライアントが実際に非推奨になっていることに気付いたので、クライアントのビルダーモデルに切り替えてみようと思いました。
var builder = AmazonS3EncryptionClientBuilder.standard()
.withEncryptionMaterials(new StaticEncryptionMaterialsProvider(encryptionMaterials))
if (accessKey.nonEmpty && secretKey.nonEmpty) builder = builder.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey.get, secretKey.get)))
builder.build()
そして...それはそれを解決しました。 Lambdaは古いモデルで認証情報を注入するのに問題があるように見えますが、新しいモデルではうまく機能します。