AWS SDK (Node.js) で S3 putObjectするときに気をつけること

どーもです。まーやです。作業中にちょっとハマったので自分用にメモ。

やりたかったこと

  • S3でstatic website hostingを実施
  • AWS Lambda 内で以下操作を行う(今回対象となるファイルはJSONファイル)
    • S3 バケツ内のファイル読み込み
    • 読み込んだファイルのデータを更新してS3へupload
  • 読み込む&uploadするファイルにはパブリックアクセス権限(everyone read)を付与したい

Lambdaは諸事情によりNode.jsで実装しました。

やったこと

S3のstatic web hostingについてはネット上にたくさん落ちているので割愛。

Lambda内でS3 getbjectもほぼチュートリアル通りに実装。
この後に、とってきたJSONを使ってごにょごにょしたかったのでPromise使って順番制御しました。

/** この変数群は後述するs3Upload functionでも利用します */
var aws = require('aws-sdk');
aws.config.region = 'us-east-1';
var s3 = new aws.S3();
var bucketName = 'alexa-demo-app';
var fileName = 'json/status.json';

function s3GetObject() {
    const getParams = {
        Bucket: [バケツの名前],
        Key: [ファイルの名前]
    };

    return new Promise(function(resolve, reject) {
        var resultJson;
        s3.getObject(getParams, function(err, data) {
            if(err) {
                resultJson = '{"status": false}';
            } else {
                resultJson = data.Body.toString();
            }
            resolve(resultJson);
        });
    });
}

ファイルのアップロード実装については、このように書いていました。

function s3Upload(statusJson) {
    const updateParams = {
        Bucket: [バケツ名],
        Key: [ファイル名],
        Body: statusJson,
        ContentType: 'application/json',
        ACL: 'public-read-write'
    };

    s3.upload(updateParams, function(err, data) {
        if(err) {
            console.log('error : ', err);
        } else {
            console.log('success : ' + bucketName + '/' + filename);
        }
    });
}

ファイル権限を付与するパラメータはACLです。ちなみにACLでは以下値が利用できます。

  • private
  • public-read
  • public-read-write
  • authenticated-read
  • aws-exec-read
  • bucket-owner-read
  • bucket-owner-full-control

また、LambdaからS3を利用するにはロールの設定が必要です。こちらのこんな感じのブログを頼りになんとなしにこんな感じのブログを頼りに ロール設定をしてみました(これが後々のダメなところ)。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    }
  ]
}

ハマったこと

前置きが長くなりましたが、ハマった事象はこちら。s3へのアップロード時に権限エラーになります。。。

Error uploading data: {[AccessDenied: Access Denied]
message: 'Access Denied',
・・・・
以下略

ACLを設定しないLambdaからのS3アップロードは過去にやったことがあったので、おかしいなと。

解決

こんなissueありました。アップロード時にアクセス権限を付与したい場合は s3:PutObjectAcl というロールActionの設定が必要なんだそうです。。。

というわけでこちらが正解のロール設定

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    }
  ]
}

解決! なんてこったい。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中