AWS CloudFormation - 從 Init 呼叫 CLI 無法獲取憑證
我正在使用 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/
希望有幫助:)