如何使用AWS Lambda将S3对象备份到另一个帐户的存储桶?

时间:2016-10-22 02:26:05

标签: amazon-web-services amazon-s3 lambda

我正在尝试使用AWS Lambda将对象从assets.myapp.com下的Account-A S3存储桶备份到backup-assets.myapp.com下的Account-B S3存储桶,但我得到了Access Denied无论我使用的是IAM还是Bucket Policy配置。

我有一个名为Backup-S3-Object的Lambda函数,它被s3:PutObject存储桶上的assets.myapp.com事件触发器触发。

所需的结果是Backup-S3-Object函数将使用适用于Javascript的AWS-SDK执行s3.copyObjectbackup-assets.myapp.com

Lambda代码

var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });

exports.backupObject = function(event, context, callback) {

    var data = event.Records[0];
    var sourceBucket = data.s3.bucket.name;
    var targetBucket = 'backup-' + data.s3.bucket.name;
    var key = data.s3.object.key;

    console.log('BACKUP: ' + sourceBucket + '/' + key + ' to ' + targetBucket);

    s3.copyObject({
        Bucket : targetBucket,
        CopySource : sourceBucket + '/' + key,
        Key : key,
        ACL : 'private',
        ServerSideEncryption : 'AES256'
    }, function(error, data) {

        if (error) return context.done(error);
        return context.done(null, 'Successful backup of ' + sourceBucket + '/' + key);

    });

};

Lambda角色S3政策

我为Backup-S3-Lambda-Role分配了我的Lambda函数的以下策略。这允许Lambda函数从List下的任何存储桶访问GetAccount-A任何对象,这是源帐户。因此,此策略将允许Lambda函数从assets.myapp.com获取对象,这是源存储桶。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:ListBucketVersions",
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::*"
            ]
        }
    ]
}

backup-assets.myapp.com广告管理政策

然后,在Account-B下,我将backup-assets.myapp.com附加了以下存储桶策略,该策略旨在允许在Account-A下运行的Lambda函数写入backup-assets.myapp.com

下的Account-B广告管理系统
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "Allow PUT from Account-A Lambda function",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:role/Backup-S3-Lambda-Role"
            },
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::backup-assets.myapp.com",
                "arn:aws:s3:::backup-assets.myapp.com/*"
            ]
        }
    ]
}

发生了什么?

assets.myapp.com水桶上的触发器发射得很好。它触发Backup-S3-Object Lambda函数,函数逻辑能够确定要复制的正确的存储桶名称和对象密钥,但它始终以Access Denied失败。

我已经使用相同的设置进行了测试并转移到同样位于Account-A下的其他存储桶,并且工作正常。所以问题显然在于跨帐户权限,但我尝试过的任何工作都没有。

我还尝试在CanonicalID广告管理系统政策中使用Account-A Principal作为backup-assets.myapp.com,但仍然得到Access Denied作为结果错误

我尝试使用"AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:root"作为主体,同样的错误。

任何帮助?

  

解决方案:如下面的Matt所述,解决方案是您需要在Lambda角色策略中包含s3:PutObject权限。   这对我来说有点奇怪,但总体思路是任何   您在您的Bucket Policy中授予Lambda角色的权限   还必须在您的域下的Lambda策略中复制目标存储桶   来源帐户。似乎Lambda角色完全被采用   当您在Bucket Policy中引用它时。为此我已经补充说   我的Lambda角色的第二个内联策略允许s3:PutObject   backup-assets.myapp.com下的Account-B广告管理系统。这是不允许的   Lambda函数写入任何源桶,但确实如此   允许它写入备份桶。

1 个答案:

答案 0 :(得分:2)

我看到两个可能的问题。

  1. 您的Lambda函数的IAM策略缺少写入到备份存储区的权限。
  2. 尝试将s3:PutObject添加到您的政策中,如下所示:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket",
                    "s3:ListBucketVersions",
                    "s3:GetObject",
                    "s3:GetObjectVersion",
                    "s3:PutObject"
                ],
                "Resource": [
                    "arn:aws:s3:::*"
                ]
            }
        ]
    }
    

    或者,如果您希望继续将Lambda函数限制为读取仅在源存储桶上访问,则可以向Lambda角色添加第二个策略,允许其{ {1}}在备份存储桶上,将备份存储桶命名为资源,如下所示:

    s3:PutObject
    1. 有时,在IAM策略中使用IAM角色作为主体并不像您一样直截了当。我不是说这是问题,但是让你放松限制,直到你得到副本工作。然后你可以收紧政策。
    2. 现在,只需让您的目标帐户访问源存储桶:

      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "s3:PutObject"
                  ],
                  "Resource": [
                      "arn:aws:s3:::backup-assets.myapp.com",
                      "arn:aws:s3:::backup-assets.myapp.com/*"
                  ]
              }
          ]
      }
      

      复制工作完成后,您可以尝试重新添加角色。