Search code examples
amazon-web-servicesaws-api-gatewayserverlessserverless-frameworkaws-serverless

How to fix Serverless error "Invalid API Key identifier specified" when using 2 stages with api keys on AWS?


I am using the following configuration to deploy a couple lambda functions to different stages prod and dev on AWS. Both stages should be protected with an api key which is stored in SSM.

serverless.yml

service: my-service
frameworkVersion: "3"

provider:
  name: aws
  runtime: nodejs16.x
  region: eu-central-1
  apiGateway:
    apiKeys:
      - name: my-apikey
        value: ${ssm:my-apikey}

functions:
  v1_myfunc:
    handler: src/api/myfunc/get_func.get
    events:
      - http:
          path: /v1/myfunc
          method: get
          private: true

plugins:
  - serverless-esbuild
  - serverless-offline
  - serverless-dotenv-plugin

My deployment scripts look like this:

package.json

"scripts": {
  "deploy:dev": "serverless deploy --stage dev",
  "deploy:prod": "serverless deploy --stage prod"
}

The problem:

When I deploy one of the stages then everything works fine. But if I deploy the other one afterwards, I always get the following error (in this case I deployed prod first, and then dev):

Deploying my-service to stage dev (eu-central-1)

✖ Stack my-service-dev failed to deploy (46s)
Environment: darwin, node 16.15.0, framework 3.23.0, plugin 6.2.2, SDK 4.3.2
Credentials: Local, "default" profile

Error:
Invalid API Key identifier specified
error Command failed with exit code 1.

Looking into AWS console, I noticed that the generated api key has the same id for both stacks (dev and prod). So, I'm guessing this is where the problem is: Both stacks sharing the same api key instance.

So, I tried to fix this by setting different api key names for each stage:

- name: my-apikey-${self:provider.stage}
  value: ${ssm:my-apikey}

But this doesn't solve the problem, as I'm still getting this error:

Invalid API Key identifier specified

Question: How do I have to change my serverless.yml config to fix the issue?


Solution

  • The api key values for both stages need to be different:

    service: my-service
    frameworkVersion: "3"
    
    provider:
      name: aws
      runtime: nodejs16.x
      region: eu-central-1
      apiGateway:
        apiKeys:
          ${self:custom.apiTest.${sls:stage}}
    functions:
      v1_myfunc:
        handler: src/api/myfunc/get_func.get
        events:
          - http:
              path: /v1/myfunc
              method: get
              private: true
    
    plugins:
     - serverless-esbuild
     - serverless-offline
     - serverless-dotenv-plugin
    
    custom:
      apiTest:
        dev: 
          - name: api-key-dev
            value: 123 # Needs to be different vs prod!
        prod: 
          - name: api-key-prod
            value: 456 # Needs to be different vs dev!