aws-valutを使ってsam deployしたい!

セキュリティーの観点からAWSアクセスキー・シークレットキーの平文保存をやめて aws-vault を使っている方も多いのではないでしょうか?

github.com

aws-vault は AWS CLI や Serverless Framework, SAM などで利用できます。

今回、aws-vault を使って sam deploy した際につまづいたのでメモとして残しておきます。

sam deploy で何が起きたのか?

サンプルのアプリケーションを作り、いざデプロイ!

$ aws-vault exec dev -- sam deploy

むむ!エラーが出ました・・

CloudFormation events from stack operations (refresh every 0.5 seconds)
-------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                    ResourceType                      LogicalResourceId                 ResourceStatusReason            
-------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                AWS::IAM::Role                    HelloWorldFunctionRole            -                               
CREATE_FAILED                     AWS::IAM::Role                    HelloWorldFunctionRole            The security token included in  
                                                                                                      the request is invalid          
                                                                                                      (Service:                       
                                                                                                      AmazonIdentityManagement;       
                                                                                                      Status Code: 403; Error Code:   
                                                                                                      InvalidClientTokenId; Request   
                                                                                                      ID: e3901e5a-9d31-4cff-93d3-5b8 
                                                                                                      ed8ecfcaa; Proxy: null)         
ROLLBACK_IN_PROGRESS              AWS::CloudFormation::Stack        sam-app                           The following resource(s)       
                                                                                                      failed to create:               
                                                                                                      [HelloWorldFunctionRole].       
                                                                                                      Rollback requested by user.     
DELETE_COMPLETE                   AWS::IAM::Role                    HelloWorldFunctionRole            -                               
ROLLBACK_COMPLETE                 AWS::CloudFormation::Stack        sam-app                           -                               
-------------------------------------------------------------------------------------------------------------------------------------
Error: Failed to create/update the stack: sam-app, Waiter StackCreateComplete failed: Waiter encountered a terminal failure state: For expression "Stacks[].StackStatus" we matched expected path: "ROLLBACK_COMPLETE" at least once

エラーの内容は、Lambda にアタッチする IAM Role が作成できなかったようです。

何が原因だったか

aws-vault は AWS STS で発行された一時的な認証情報を使って、AWS リソースへアクセスします。

このとき GetSessionTokenAPI リクエストで一時認証が発行されます。

この GetSessionToken に IAM に関する制約があるようで、公式のドキュメントにも以下ように記載がありました。

docs.aws.amazon.com

Cannot call IAM API operations unless MFA information is included with the request.

リクエストにMFA情報が含まれていないと、IAM API オペレーションは呼び出せません

なるほど!

MFA を設定してリトライ!

原因がわかったところで、config ファイルを修正して・・

[profile dev]
region=ap-northeast-1
mfa_serial=arn:aws:iam::<AWS Account ID>:mfa/<IAM User>

再度 deploy!

CloudFormation events from stack operations (refresh every 0.5 seconds)
-------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                    ResourceType                      LogicalResourceId                 ResourceStatusReason            
-------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                AWS::IAM::Role                    HelloWorldFunctionRole            -                               
CREATE_IN_PROGRESS                AWS::IAM::Role                    HelloWorldFunctionRole            Resource creation Initiated     
CREATE_COMPLETE                   AWS::IAM::Role                    HelloWorldFunctionRole            -                               
CREATE_IN_PROGRESS                AWS::Lambda::Function             HelloWorldFunction                -                               
CREATE_IN_PROGRESS                AWS::Lambda::Function             HelloWorldFunction                Resource creation Initiated     
CREATE_COMPLETE                   AWS::Lambda::Function             HelloWorldFunction                -                               
CREATE_IN_PROGRESS                AWS::ApiGateway::RestApi          ServerlessRestApi                 -                               
CREATE_IN_PROGRESS                AWS::ApiGateway::RestApi          ServerlessRestApi                 Resource creation Initiated     
CREATE_COMPLETE                   AWS::ApiGateway::RestApi          ServerlessRestApi                 -                               
CREATE_IN_PROGRESS                AWS::Lambda::Permission           HelloWorldFunctionHelloWorldPer   -                               
                                                                    missionProd                                                       
CREATE_IN_PROGRESS                AWS::ApiGateway::Deployment       ServerlessRestApiDeployment47fc   -                               
                                                                    2d5f9d                                                            
CREATE_IN_PROGRESS                AWS::Lambda::Permission           HelloWorldFunctionHelloWorldPer   Resource creation Initiated     
                                                                    missionProd                                                       
CREATE_IN_PROGRESS                AWS::ApiGateway::Deployment       ServerlessRestApiDeployment47fc   Resource creation Initiated     
                                                                    2d5f9d                                                            
CREATE_COMPLETE                   AWS::ApiGateway::Deployment       ServerlessRestApiDeployment47fc   -                               
                                                                    2d5f9d                                                            
CREATE_IN_PROGRESS                AWS::ApiGateway::Stage            ServerlessRestApiProdStage        -                               
CREATE_IN_PROGRESS                AWS::ApiGateway::Stage            ServerlessRestApiProdStage        Resource creation Initiated     
CREATE_COMPLETE                   AWS::ApiGateway::Stage            ServerlessRestApiProdStage        -                               
CREATE_COMPLETE                   AWS::Lambda::Permission           HelloWorldFunctionHelloWorldPer   -                               
                                                                    missionProd                                                       
CREATE_COMPLETE                   AWS::CloudFormation::Stack        sam-app                           -                               
-------------------------------------------------------------------------------------------------------------------------------------

今度は無事にデプロイできたようです🎉

最後に

この STS GetSessionToken の制約は SAM だけではなく、AWS CLI や Serverless Framework でも共通です。 aws-valut を使う際は MFA の設定をしておくことをおすすめします!