Amazon-Web-Services

AWS CloudFormation - 從 Init 呼叫 CLI 無法獲取憑證

  • July 17, 2017

我正在使用 CloudFormation 模板來啟動自定義Windows AMI,它需要從 S3 儲存桶中檢索一些程式碼並在啟動後執行它。

在使用 AWS CLI ( ) 快速能夠手動完成之後,s3 sync我一直在努力通過 CloudFormation 讓它工作超過 8 小時,但無濟於事。從本質上講,這個命令總是失敗的:

“NoCredentialsError:無法找到憑據”

最初我嘗試以多種不同的方式設置/.aws/credentials/.aws/config文件,直到我最終意識到正在執行的使用者身份cfn-init.exe及其子程序根本無法訪問這些文件,這將無法正常工作。因此,我選擇使用 設置環境變數setx,但這似乎也不起作用,而且我仍然遇到同樣的錯誤。

我對此感到非常沮喪,因為每次測試都需要更改 CF 模板,上傳到 S3,創建堆棧,等待 5-10 分鐘才能完成僅引導到 RDP 並再次發現它失敗

init > config是我的模板的一部分:

"commands" : {
 "0-Tester" : {
   "command" : "echo \"I am OK.\" > \"d:\\test.txt\""
 },
 "1-SetAK" : {
   "command" : { "Fn::Join" : ["", [
     "setx AWS_ACCESS_KEY_ID ",
     { "Ref": "AutomationUserAK" }
   ]] }
 },
 "2-SetSK" : {
   "command" : { "Fn::Join" : ["", [
     "setx AWS_SECRET_ACCESS_KEY ",
     { "Ref": "AutomationUserSK" }
   ]] }
 },
 "3-Pullcode" : {
   "command" : "aws s3 sync s3://some-s3-bucket d:/dev/ --debug"
 }
}

前 3 個命令(Tester、SetAK、SetSK)工作得很好。最後一個(Pullcode)每次都失敗。

所以在這一點上,我假設我做錯了。也許我需要為 CF 堆棧配置一個特定的 IAM,也許我應該使用setx ... /M,也許還有一百萬個其他選項,但是由於這種反複試驗已經持續了我整個工作日,然後我認為它不會傷心地問。

您的每個命令都在單獨的 PowerShell 中執行,因此setx AWS_ACCESS_KEY_ID將變數設置在一個shell 實例中並退出。然後在的shellsetx AWS_SECRET_ACCESS_KEY中設置另一個變數並退出。然後,您在另一個shell 中執行,其中不存在先前的變數,並且它失敗,因為**該shell中不存在憑據變數。aws s3 sync

您可以執行以下操作,而不是從元數據中呼叫它:

"UserData": {
 "Fn::Base64": { "Fn::Join": ["", [
   "<script>\n",
   "cfn-init.exe -v -s [...]\n",
   "setx AWS_ACCESS_KEY_ID ", { "Ref": "AutomationUserAK" }, "\n",
   "setx AWS_SECRET_ACCESS_KEY ", { "Ref": "AutomationUserSK" }, "\n",
   "aws s3 sync s3://some-s3-bucket d:/dev/\n",
   "</script>"
 ] ] }
}

在這種情況下,它將全部在同一個 shell 實例中執行,並且當您呼叫aws s3 sync.

改用 IAM 角色

但是我不得不說,將訪問和密鑰傳遞給 CloudFormation 模板是一種不好的做法。相反,CloudFormation 模板應創建具有適當權限的IAM 角色,以訪問 S3 儲存桶並將其分配給 EC2 實例。實例上的aws工具將擁有對 S3 的透明訪問,而無需提供訪問和密鑰。這樣的事情應該為您的 CloudFormation 模板做:

首先使用S3 訪問策略創建****IAM 角色(根據您的需要調整策略):

"InstanceRole": {
 "Type": "AWS::IAM::Role",
 "Properties": {
   "AssumeRolePolicyDocument": {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": { "Service": [ "ec2.amazonaws.com" ] },
         "Action": [ "sts:AssumeRole" ]
       }
     ]
   },
   "Path": "/",
   "Policies": [
     { 
       "PolicyName": "S3_Access",
       "PolicyDocument": {
         "Statement": [
           {
             "Effect": "Allow",
             "Action": [ "s3:List*", "s3:Get*" ],
             "Resource": "*"
           }
         ]
       }
     }
   ]
 }
},

然後創建一個引用上述 IAM 角色的IAM Instance Profile …

"InstanceProfile": {
 "Type": "AWS::IAM::InstanceProfile",
 "Properties": {
   "Path": "/",
   "Roles": [ { "Ref": "InstanceRole" }
   ]
 }
},

最後創建分配該IAM 配置文件的 EC2 實例(進而創建具有 S3 訪問策略的IAM 角色)。

"Instance": {
 "Type": "AWS::EC2::Instance",
 "Properties": {
   "IamInstanceProfile": { "Ref": "InstanceProfile" },
   [...],
   "UserData": {
     "Fn::Base64": { "Fn::Join": ["", [
       "<script>\n",
       "cfn-init.exe -v -s ", { "Ref" : "AWS::StackId" }, " -r Instance --region ", { "Ref" : "AWS::Region" }, "\n",
       "</script>"
     ] ] }
   }
 },
 "Metadata": {
   "AWS::CloudFormation::Init": {
     "config": {
       "commands" : {
         "Pullcode" : {
           "command" : "aws s3 sync s3://some-s3-bucket d:/dev/ --debug"
         }
       }
     } 
   }
 }
},

使用IAM 角色時,AWS 憑證aws是由命令動態生成和透明獲取的。這是讓 EC2 實例訪問 AWS 資源的更安全和更可取的方式。

在此處了解有關 EC2 實例角色的更多資訊:https ://aws.nz/best-practice/ec2-instance-roles/

希望有幫助:)

引用自:https://serverfault.com/questions/862050