2016-10-22 161 views
3

我試圖使用AWS lambda來備份對象從assets.myapp.com S3桶Account-A下一個backup-assets.myapp.com S3存儲Account-B下,但我越來越Access Denied無論IAMBucket Policy配置我使用。如何使用AWS Lambda將S3對象備份到另一個帳戶上的存儲桶?

我有一個名爲Backup-S3-Object的Lambda函數,它由assets.myapp.com存儲桶中的s3:PutObject事件觸發器觸發。

期望的結果是Backup-S3-Object函數將使用適用於Javascript的AWS-SDK執行s3.copyObjectbackup-assets.myapp.com

拉姆達代碼

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); 

    }); 

}; 

拉姆達作用S3政策

我已經得到了分配給我的lambda函數的Backup-S3-Lambda-Role以下策略。這允許Lambda函數訪問ListGet任何對象,來自任何存儲桶,位於源帳戶Account-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以下桶的政策,其目的是讓lambda函數,Account-A下運行,以寫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桶上的觸發器觸發得很好。它會觸發Lambda函數Backup-S3-Object,並且函數邏輯能夠確定要複製的正確存儲桶名稱和對象關鍵字,但它始終會因爲Access Denied而失敗。

我已經做了一個測試,使用相同的設置,並轉移到另一個存儲桶,也在Account-A,它工作得很好。所以這個問題顯然與跨賬戶權限有關,但我沒有嘗試過。

我也使用Account-ACanonicalID作爲backup-assets.myapp.com桶政策Principal嘗試,但仍然得到Access Denied作爲所產生的誤差。

我試圖用"AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:root"作爲主體,同樣的錯誤。

任何幫助?

一個解決方案:正如描述的以下馬特的解決方案是,你需要包括s3:PutObject許可在lambda作用的政策。 這對我來說有點奇怪,但總體思路是,您在您的 目標存儲桶的存儲桶政策中授予您的Lambda角色的任何 權限也必須在您的 源帳戶下的Lambda政策中進行復制。當您在Bucket Policy中引用它時,似乎Lambda角色是已採用完全是 。爲了實現此目的,我已將 第二個內聯策略添加到我的Lambda角色中,該角色允許s3:PutObject至 ,backup-assets.myapp.com存儲桶在Account-B之下。這不允許 Lambda函數寫入任何源桶,但是 允許它寫入備份桶。

回答

2

我看到兩個可能的問題。

  1. 您爲您的lambda函數IAM策略缺少權限到備份桶。

嘗試增加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函數來只讀您的源桶(S)訪問,你可以允許它在你的備份桶添加第二個政策,您LAMBDA作用s3:PutObject,命名備份桶作爲資源,像這樣:

{ 
    "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/*" 
      ] 
     } 
    ] 
} 
  • 有時,在您的IAM策略中使用IAM角色作爲委託人並不像您那樣直截了當。我並不是說這是問題,但是讓我們放鬆這些限制,直到您獲得複印件的工作。那麼你可以收緊政策。
  • 現在,只是讓你的目標帳戶訪問源鬥:

    { 
        "Version": "2008-10-17", 
        "Id": "Backup-Assets", 
        "Statement": [ 
         { 
          "Sid": "Allow PUT from Account-A Lambda function", 
          "Effect": "Allow", 
          "Principal": { 
           "AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:root" 
          }, 
          "Action": "s3:*", 
          "Resource": [ 
           "arn:aws:s3:::backup-assets.myapp.com", 
           "arn:aws:s3:::backup-assets.myapp.com/*" 
          ] 
         } 
        ] 
    } 
    

    一旦複製工作,你可以嘗試添加的角色了。

    +0

    感謝@Matt Houser的回答,但我認爲你的政策混淆了。 'Backup-S3-Object'Lambda角色只在源桶('assets.myapp.com')上擁有'List'和'Get'權限,因爲它只需從那裏獲取對象,不需要寫入任何東西到那個桶。然後,我使用'backup-assets.myapp.com'上的桶策略來允許Lamba角色寫入'Account-B'下的備份桶。我已經試過授予'arn:aws:iam:ACCOUNT-A-NUMBER-HERE:root',但是我會再給它一次。但我認爲Lambda函數不會在'root'下激發,不確定。 – AJB

    +0

    是的,使用'root'主體的同樣的問題。 – AJB

    +0

    好吧,這是搞砸了。當我將's3:PutObject'添加到Lambda角色策略時,它可以工作。但爲什麼?該策略應該規定Lambda函數對源桶「assets.myapp.com」的權限,該權限只需**讀取**。爲什麼它要求源桶上的'PUT'信號將一個對象複製到'backup-assets.myapp.com'桶中? – AJB

    相關問題