serverless / serverless

⚡ Serverless Framework – Effortlessly build apps that auto-scale, incur zero costs when idle, and require minimal maintenance using AWS Lambda and other managed cloud services.
https://serverless.com
MIT License
46.62k stars 5.74k forks source link

Custom Plugin using configurationVariablesSources seems to be parsing differently in v4 vs v3 #12974

Closed georgesglynn closed 2 months ago

georgesglynn commented 2 months ago

Issue description

For custom plugins (docs), it appears the parsing has changed during the upgrade from v3 to v4. I've illuminated my observations below:

In v3, this is the snippet of my config:

plugins:
  - ./KMSPlugin.js
...
custom:
  kmsEast: ${customKmsKey:us-east-1:alias/test_${aws:accountId}_kms}
  kmsWest: ${customKmsKey:us-west-2:alias/test_${aws:accountId}_kms}

And my KMSPlugin.js was written in the following way:

"use strict";
const { KMSClient, DescribeKeyCommand } = require("@aws-sdk/client-kms");

async function getKmsKeyByAlias(alias, region) {
  const client = new KMSClient({
    region: region,
  });

  const input = {
    // DescribeKeyRequest
    KeyId: alias,
  };
  const command = new DescribeKeyCommand(input);
  return await client.send(command);
}
class KMSPlugin {
  constructor(serverless) {
    this.serverless = serverless;
    this.configurationVariablesSources = {
      customKmsKey: {
        async resolve({ address }) {
          let params = address.split(":");
          const region = params[0];
          const alias = params[1];
          const keyInfo = await getKmsKeyByAlias(alias, region);
          serverless.cli.log(`Info: ${region} ${alias} ARN: ${keyInfo.KeyMetadata.Arn}`);
          return {
            value: `${keyInfo.KeyMetadata.Arn}`,
          };
        },
      },
    };
  }
}

module.exports = KMSPlugin;

After upgrading to v4, I am getting the following error on the above config during sls deploy:

> sls deploy --stage dev3

✖ Error: us-east-1 resolver of provider customKmsKey not found
    at #getResolver (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:51699)
    at _ResolverManager.resolve (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:57206)
    at #handlePlaceholderNode (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:55970)
    at file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:53920
    at processNodeAndHandleCompletion (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:44842)
    at processNodeAndManagePromise (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:45480)
    at file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:45297
    at Array.forEach (<anonymous>)
    at processSinks (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:45252)
    at processGraphInParallel (file:///Users/TEST/.serverless/releases/4.4.18/package/dist/sf-core.js:693:45095)

For help, try the following:
  • Run the command again with the "--debug" option
  • Run "serverless support"
  • Review the docs: https://www.serverless.com/framework/docs/

I have observed that this is related to an apparent severless-v4-parsing of the : in the expected variable (address parameter in the plugin code). If I remove the :, and replace it with a different delimiter, the deployment will succeed.

I am seeking to understand the details which caused this new behavior.

Please advise if I can provide anymore helpful detail.

Thank you for your time!

-George

Context

N/A

czubocha commented 2 months ago

Hi @georgesglynn,

This issue stems from introducing Variable Resolvers in v4. In v4, variables are parsed into three sections using a colon (:) as the delimiter: ${provider:resolver:key}. A single provider can now have multiple resolvers, for example, ${aws:s3:key} and ${aws:ssm:key}. This is why you’re encountering the error us-east-1 resolver of provider customKmsKey not found when using the : delimiter.

Plugins' configurationVariablesSources are now treated as providers with a single resolver, and both the provider and resolver share the same name as the variable source. To continue using the colon delimiter, you can adjust your syntax to ${provider:resolver:key}. For your use case, this would be: ${customKmsKey:customKmsKey:us-east-1:alias/test_${aws:accountId}_kms}.