Serverless Frameworkをv1.65.0にバージョンアップしたらAWS IAMロール名の長さ制限エラーが出た

f:id:kidani_a:20200305232529p:plain

CI環境でnpm i -g serverlessからsls deployを実行したら、ある時急にエラーが出るようになったので対処方法などをまとめておく。

 

 

[Serverless Framework v1.65.0の仕様変更]

2020年3月上旬現在最新であるServerless Framework v1.65.0から、AWS Lambda関数に付与されるIAMロール名の生成ロジックが変更になった。

 

こちらのプルリクエストがその変更に該当する。

github.com

 IAMロールの命名規則は次のように変化した。

  • v1.64.1:${service}-${stage}-${region}-lambdaRole
  • v1.65.0:${stackName}-${region}-lambdaRole

 

プルリクエストの中でレビュアのmedikoo氏が述べている通り、独自のスタック名(stackName)を定義していなければ、${stackName} = ${service}-${stage}なので問題がない。反対に言えば、独自のスタック名を定義している場合には、問題が発生する。

 

例として、次のような比較的シンプルなserverless.ymlを考える*1

シンプルだが、providerのところで無駄に長いstackNameを独自に定義しているところが今回のポイントである。

service: sls1-65-0-roletest
provider:
  region: ap-northeast-1
  name: aws
  runtime: python3.8
  stackName: serverless-framework-version-1-65-0-test-stack
  iamRoleStatements:
    - Effect: Allow
      Action:
        - 's3:ListBucket'
      Resource: '*'
functions:
  hello:
    handler: handler.hello
    events: []
    name: sls1-65-0-roletest-dev-hello

 

この場合、先にあげた命名規則の変更により、Lambda関数helloに適用されるIAMロールの命名は次のようになる。

  • v1.64.1:sls1-65-0-roletest-dev-ap-northeast-1-lambdaRole(48文字)
  • v1.65.0:serverless-framework-version-1-65-0-test-stack-ap-northeast-1-lambdaRole(72文字)

sls packageコマンドで生成されたserverless-state.jsonを比較すると一目瞭然である。

f:id:kidani_a:20200306001853p:plain

 

ここで重要になるのが、AWS IAMの文字数制限である。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_iam-limits.html

AWSのドキュメントによると、IAMロール名の制限は64文字であるらしい(エラーが出るまで知らなかった)。

 

従って、Serverless Framework v1.64.1では上記のserverless.ymlをデプロイすることができるが、Serverless Framework v1.65.0を利用するとIAMロール名が8文字分上限を超えてしまうため、次のようにエラーとなってしまう。

$ sls --version
Framework Core: 1.65.0
Plugin: 3.4.1
SDK: 2.3.0
Components: 2.22.3

$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service sls1-65-0-roletest.zip file to S3 (410 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
....
Serverless: Operation failed!
Serverless: View the full error output: https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stack/detail?stackId=arn%3Aaws%3Acloudformation%3Aap-northeast-1%3AXXXXXXXXXXXX%3Astack%2Fserverless-framework-version-1-65-0-test-stack%2FXXXXX
 
  Serverless Error ---------------------------------------
 
  An error occurred: IamRoleLambdaExecution - 1 validation error detected: Value 'serverless-framework-version-1-65-0-test-stack-ap-northeast-1-lambdaRole' at 'roleName' failed to satisfy constraint: Member must have length less than or equal to 64 (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: XXXXX).
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information ---------------------------
     Operating System:          darwin
     Node Version:              10.15.0
     Framework Version:         1.65.0
     Plugin Version:            3.4.1
     SDK Version:               2.3.0
     Components Version:        2.22.3

 

[対処方法1:スタック名を変更する]

上記のエラーに対応するには、以下のいずれかの方法でスタック名を変更すれば良い。

  1. stackNameで定義している名称を短くする
  2. stackNameを定義せず、短いservice名とstage名の組み合わせをstackNameとする

 

しかし、いずれの場合でも、CloudFormationとしてのスタック名が変更となってしまう。このため、v1.64.1以前のバージョンで既にServerless Applicationをデプロイしている場合には以前のCloudFormationスタックを名前で特定することができず、古いスタックが削除されないので注意したい。

古いスタックはたいていの場合不要なので、手動で削除する必要がある。

 

[対処方法2:旧バージョンのServerless Frameworkを利用する]

今回は、CIのジョブが以下のように定義されていた。

    - npm i -g serverless
    - sls deploy

 

単にnpm i -g serverlessと実行すると、利用可能な最新バージョンがインストールされる。このため、今回のように意図しない修正が含まれている場合、デプロイができずにエラーとなる可能性がある。

 

これを回避するには、以下のように利用するServerless Frameworkのバージョンを固定すれば良い。

    - npm i -g serverless@1.64.1
    - sls deploy

 

ただしこの場合、いつか新機能が実装され、その機能を利用しようとServerless Frameworkをバージョンアップした際に今回の問題に該当する可能性があるため、注意が必要である。

 

[まとめ]

  • Serverless Frameworkをv1.65.0にバージョンアップしてデプロイしたらIAMロール名の長さ制限エラーが出た
  • 独自に定義している長いスタック名を短縮するか、スタック名を定義するのをやめることで回避できる
  • あるいは、v1.64.1以前のServerless Frameworkを使い続けることでも回避できる
  • 検証に利用したコードは以下のリポジトリにコミットしてある  

github.com

*1:この例ではAWS Lambdaで利用するメモリサイズは考慮していない。Serverless Frameworkのデフォルトが1024MBなので用途に応じて変更した方が良いだろう。https://kdnakt.hatenablog.com/entry/2018/08/22/080000