serverless / serverless

⚡ Serverless Framework – Use AWS Lambda and other managed cloud services to build apps that auto-scale, cost nothing when idle, and boast radically low maintenance.
https://serverless.com
MIT License
46.3k stars 5.7k forks source link

Deploy function layer resolution incorrectly failing cloudformation schema check #7253

Open nkeating-mutualofenumclaw opened 4 years ago

nkeating-mutualofenumclaw commented 4 years ago

Bug Report

Description

When performing a sls deploy function there appears to be a schema check which is failing when using resolve notation as the layer arn. Performing a sls deploy on the same stack succeeds.

Resolve Schema: layers:

  1. What did you do? Leveraging secrets to hold dynamic configurations for layers, as old layers that are removed can result in stacks no longer being able to roll back
  2. What happened? sls deploy function fails, while sls deploy succeeds

Error: 1 validation error detected: Value '[{{resolve:secretsmanager:layers/nucleus-core-dev-lib-services:SecretString:latest}}]' at 'layers' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 140, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: (arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-]+:[0-9]+)|(arn:[a-zA-Z0-9-]+:lambda:::awslayer:[a-zA-Z0-9-]+)]

Validating the serverless yml file should not be done on deploy function, as it is also not done on deploy. If there is a desire to validate the cloudformation this should be done using the cloudformation cli validate-template.

  1. What should've happened? sls deploy function should succeed and should not be performing custom validation on cloudformation.

  2. What's the content of your serverless.yml file? Fairly complex, but the repro can be done with a simple function, with a layer that references a secret for the layer arn.

  3. What's the output you get when you use the SLS_DEBUG=* environment variable (e.g. SLS_DEBUG=* serverless deploy)

Serverless: [serverless-plugin-epsagon] Wrapping your functions with Epsagon... Serverless: Bundling with Webpack... [hardsource:446bec07] Using 4 MB of disk space. [hardsource:446bec07] Tracking node dependencies with: package-lock.json. [hardsource:446bec07] Reading from cache 446bec07... Time: 552ms Built at: 01/23/2020 5:07:15 PM Asset Size Chunks Chunk Names epsagon_handlers/associatePolicies-epsagon.js 10.9 KiB epsagon_handlers/associatePolicies-epsagon [emitted] epsagon_handlers/associatePolicies-epsagon epsagon_handlers/associatePolicies-epsagon.js.map 12.3 KiB epsagon_handlers/associatePolicies-epsagon [emitted] [dev] epsagon_handlers/associatePolicies-epsagon Entrypoint epsagon_handlers/associatePolicies-epsagon = epsagon_handlers/associatePolicies-epsagon.js epsagon_handlers/associatePolicies-epsagon.js.map [./epsagon_handlers/associatePolicies-epsagon.ts] 432 bytes {epsagon_handlers/associatePolicies-epsagon} [./src/functions/associatePolicies.ts] 5.33 KiB {epsagon_handlers/associatePolicies-epsagon} [aws-sdk] external "aws-sdk" 42 bytes {epsagon_handlers/associatePolicies-epsagon} [built] [epsagon] external "epsagon" 42 bytes {epsagon_handlers/associatePolicies-epsagon} [built] [policysystem] external "policysystem" 42 bytes {epsagon_handlers/associatePolicies-epsagon} [built] Serverless: Packaging function: associatePolicies... Serverless: Code not changed. Skipping function deployment.

Serverless Error ---------------------------------------

1 validation error detected: Value '[{{resolve:secretsmanager:layers/nucleus-core-dev-lib-services:SecretString:latest}}]' at 'layers' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 140, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: (arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-]+:[0-9]+)|(arn:[a-zA-Z0-9-]+:lambda:::awslayer:[a-zA-Z0-9-]+)]

Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com

Your Environment Information --------------------------- Operating System: win32 Node Version: 10.15.3 Framework Version: 1.60.4 Plugin Version: 3.2.6 SDK Version: 2.2.1 Components Core Version: 1.1.2 Components CLI Version: 1.4.0

Similar or dependent issues:

medikoo commented 4 years ago

Thanks @nkeating-mutualofenumclaw for reporting! PR that fixes that is welcome

rdsedmundo commented 4 years ago

When you use the deploy function you're skipping CloudFormation altogether so this expression can't be resolved, which means that the error you're seeing is not a validation done by the framework but the result of the Lambda API by itself which is receiving the uncomputed, raw expression, as the layers parameter.

Alternatively, you can ask the framework to resolve the value during deployment and pass it directly to the API:

functions:
  hello:
    handler: src/handler.hello
    layers:
      - '${ssm:/aws/reference/secretsmanager/lambdalayer~true}'
      # - '{{resolve:secretsmanager:lambdalayer}}'

Bear in mind though that deploy function is not intended for production usage, as you're drifting your CloudFormation stack state.

markl-vesper commented 4 years ago

Was just about to log an issue for something very similar

What we see happening is that when you deploy a function via serverless the secrets value in the lambda environment is is overwritten with the actual definition of the secret from the stack.yml ie

"{{resolve:secretsmanager:SecretName:SecretString:FieldName}}"

redeploying the stack will not fix the now invalid secret. Only way to fix is to remove stack and deploy. Other secrets are not invalidated since serverless is able to resolve them vs secrets manager which needs to be resolved by CF (we believe)

medikoo commented 2 years ago

I believe the right fix here, is to improve layers resolution for function deploy, and not apply the setting if there are CF variables used in a string (Currently we're skipping them, when we detect they're configured via CF intrinsic functions: https://github.com/serverless/serverless/blob/4c341b154096629341aecb99dd69117447bb1557/lib/plugins/aws/deployFunction.js#L291-L293)