2021/04/14 追記
3行で頼む
- serverless frameworkをv1 → v2にアップデートした後、
Modifying service token is not allowed
が発生してデプロイ失敗 - https://forum.serverless.com/t/modifying-service-token-is-not-allowed/12404 を参考にして、stageオプションを省略せずに指定したらデプロイ成功した
- (調べた限り) バージョン2.32.0以降で、serverless.ymlにpluginsを指定していて、Custom Resourceを作成する設定があると発生する
発生した事象
serverless frameworkを 1.78.1 → 2.33.1 にアップデートして、デプロイ実行したらModifying service token is not allowed
エラーとなり失敗した。
$ npx sls deploy
Serverless: Deprecation warning: CLI options definitions were upgraded with "type" property (which could be one of "string", "boolean", "multiple"). Below listed plugins do not predefine type for introduced options:
- Prune for "number", "stage", "region", "function", "layer", "includeLayers", "dryRun"
Please report this issue in plugin issue tracker.
Starting with next major release, this will be communicated with a thrown error.
More Info: https://www.serverless.com/framework/docs/deprecations/#CLI_OPTIONS_SCHEMA
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Installing dependencies for custom CloudFormation resources...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service xxx.zip file to S3 (13.53 MB)...
Serverless: Uploading custom CloudFormation resources...
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%xxx-dev%2F2ecb8c70-9d8e-11ea-87ef-0af0ae9d5064
Serverless Error ----------------------------------------
An error occurred: XXXCustomS31 - Modifying service token is not allowed..
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information ---------------------------
Operating System: darwin
Node Version: 14.16.1
Framework Version: 2.33.1 (local)
Plugin Version: 4.5.3
SDK Version: 4.2.2
Components Version: 3.8.1
上記エラーは XXXCustomS31 というCustom Resourceの更新で発生している。
このCustom Resourceはevents.s3
にexisting: true
を設定すると作成されるもので、1.78.1 の時に作成している。
# serverless.yml
func:
handler: bin/func
events:
- s3:
bucket: xxxx
event: s3:ObjectCreated:*
rules:
- suffix: .txt
existing: true
Modifying service token is not allowed
はどんなエラーか?
Custom ResourceのServiceTokenを変更しようとして失敗している。
- 参考
- https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html
- ServiceTokenは Updates are not supported. と書いてある
- https://forums.aws.amazon.com/thread.jspa?messageID=713762
- https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html
何故ServiceTokenは変わったのか?
Custom Resourceの定義は以下の通り。ServiceTokenには、existing: true
を指定した時にframework側で作成するLambda関数のARNを指定している。
Custom ResourceのCloudFormation定義
// .serverless/cloudformation-template-update-stack.json
"XXXCustomS31": {
"Type": "Custom::S3",
...
"Properties": {
"ServiceToken": {
"Fn::GetAtt": [
"CustomDashresourceDashexistingDashs3LambdaFunction",
"Arn"
]
},
...
(1.78.1の) 該当関数のCloudFormation定義
// .serverless/cloudformation-template-update-stack.json
"CustomDashresourceDashexistingDashs3LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Ref": "ServerlessDeploymentBucket"
},
"S3Key": "serverless/xxx/dev/1617775748688-2021-04-07T06:09:08.688Z/custom-resources.zip"
},
"FunctionName": "xxx-dev-custom-resource-existing-s3",
"Handler": "s3/handler.handler",
"MemorySize": 1024,
"Runtime": "nodejs12.x",
"Timeout": 180,
"Role": {
"Fn::GetAtt": [
"IamRoleCustomResourcesLambdaExecution",
"Arn"
]
}
},
"DependsOn": [
"IamRoleCustomResourcesLambdaExecution"
]
},
(2.33.1の) 該当関数のCloudFormation定義
// .serverless/cloudformation-template-update-stack.json
"CustomDashresourceDashexistingDashs3LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Ref": "ServerlessDeploymentBucket"
},
"S3Key": "serverless/xxx/dev/1617775041490-2021-04-07T05:57:21.490Z/custom-resources.zip"
},
"FunctionName": "xxx-undefined-custom-resource-existing-s3",
"Handler": "s3/handler.handler",
"MemorySize": 1024,
"Runtime": "nodejs12.x",
"Timeout": 180,
"Role": {
"Fn::GetAtt": [
"IamRoleCustomResourcesLambdaExecution",
"Arn"
]
}
},
"DependsOn": [
"IamRoleCustomResourcesLambdaExecution"
]
},
1.78.1 のFunctionNameには、stageである dev が含まれていたが、2.33.1 ではその部分が undefined になっている。
2.33.1 のスタックでデプロイすると、
- FunctionNameがかわる = 新しい関数を作成しようとする
- 新しい関数のARNをCustom ResourceのServiceTokenに反映(更新)しようとして失敗した
ということらしい。
対応策
https://forum.serverless.com/t/modifying-service-token-is-not-allowed/12404
に書いてある通り、sls deploy
にstageオプションを明示することで回避できた。
発生条件を調べる
以下の方法で調べたところ、2.32.0からこの事象が発生する。
# <version>を落として、正しいFunctionNameを取得できるまで繰り返す
$ npm i -D serverless@<version>
$ npx sls package
$ cat .serverless/cloudformation-template-update-stack.json | jq .Resources.CustomDashresourceDashexistingDashs3LambdaFunction.Properties.FunctionName
“xxxx-undefined-custom-resource-existing-s3”
関連PRは https://github.com/serverless/serverless/pull/9171 。
2.31.0 以前の挙動
lib/plugins/aws/lib/validate.jsのoptions
がpluginManager.cliOptions
を参照しているので、このタイミングでcliOptions.stage
を設定していた。
そして、lib/plugins/aws/customResources/index.jsでcliOptions.stage
を取得して関数名に dev を設定していた。
2.32.0 以降の挙動
プラグインのoptions
にpluginManager.cliOptions
を設定するための serverless.init()
の実行より後に scripts/serverless.jsで
pluginManager.cliOptions
を別のオブジェクトに更新しているので、プラグインのoptions
はcliOptions
を参照しない。
validate.js の処理を通過しても、参照していないcliOptions.stage
は undefined のままで、それが関数名に設定される。
上記コードを実行するのは、serverless.ymlで外部プラグインを追加している場合だけで、設定していたプラグインを全て外してパッケージを作ってみたら正しい関数名になっていた。
おわり
ちょっとserverless frameworkに詳しくなった。 もしまだ無かったらIssueかPRを投げたい。