Referencing an ApiGateway UsagePlan by ID

I am creating usage plans for api gateway in my serverless configuration. I would like to get the ID of the created plans and put them in environment variables. The reason for this is to reference the usage plans within a lambda to associate newly created api keys with a particular plan.

provider:
  ...
  apiGateway:
    usagePlan:
      - free:
          quota:
            limit: 1000
            offset: 0
            period: MONTH

  environment:
    USAGE_PLAN_FREE_ID: # what to put here?

I did some searching and found this post, but its really old and I don’t think this approach still works

Thank you guys for keeping this community strong :slight_smile:

Or, I think a different way to handle this would be to manually set the name for the usage plan, instead of letting serverless create the name. Unfortunately, I haven’t found a way to get this to work either.

  apiGateway:
    usagePlan:
      - free:
          name: my-custom-name # unrecognized property
          quota:
            limit: 1000
            offset: 0
            period: MONTH

After several hours, I finally figured this out myself. For those who are looking for this solution, you need to reference the CloudFormation resource that gets generated by serverless. This is done using the “Ref” method and making sure you get the naming correct. You can read more in the link below. For my problem, it meant concatenating the name of the plan with the first letter capitalized. Also, putting the environment variables on the provider leads to a circular dependency. So I had to move it to the lambda function.

provider:
  apiGateway:
    usagePlan:
      - free:
          quota:
            limit: 1000
            offset: 0
            period: MONTH

functions:
  myFunction:
    environment:
      USAGE_PLAN_FREE_ID: { "Ref": "ApiGatewayUsagePlanFree" }

Unfortunately, I am still working on this and running into issues. The method posted above works great for an isolated lambda function.

If I add an api gateway event to trigger the lambda function, I get a long circular dependency chain. Essentially the gateway depends on the lambda, but adding the “Ref” and an event causes the lambda to depend on the gateway.

I have no idea how to resolve this issue. If you guys have any advice for me, please share, thanks.

Error: The CloudFormation template is invalid: Circular dependency between resources: [CreateKeyLambdaVersioneOpZrqC8mpUGLztEz3wzGrzZJDqxNuyFs4odZqt8c, ApiGatewayUsagePlanFree, CreateKeyLambdaPermissionApiGateway, CreateKeyLambdaFunction, ApiGatewayMethodKeysPost, ApiGatewayDeployment1612115480987]

provider:
  apiGateway:

    usagePlan:

      - free:
          quota:
            limit: 10
            offset: 0
            period: MONTH

functions:
  createKey:
    handler: functions/createKey.handler
    events:
      - http:
          path: keys
          method: post
          cors: true
    environment:
      USAGE_PLAN_FREE_ID: { "Ref": "ApiGatewayUsagePlanFree" }

Running into exactly this problem. I do not understand why the gateway depends on the lambda. If I create the api gateway and usage plan separately using whatever method, save the ids in ssm and refer to them in serverless.yml, everything would have been fine.

Can someone from serverless explain?

We manage to solve this by separating the UsagePlan to a separate resource

resources:
  Resources:
    UsagePlan:
      Type: AWS::ApiGateway::UsagePlan
      Properties:
        UsagePlanName: ${self:custom.usagePlanName}
        ApiStages:
          - ApiId: !Ref ApiGatewayRestApi
            Stage: ${self:provider.stage}


functions:
  create_api_key:
    handler: src/handlers/apiKeyCreate.handler
    iamRoleStatements:
      - Effect: Allow
        Action:
          - apigateway:*
        Resource: "*"
    environment:
      USAGE_PLAN_ID: !Ref UsagePlan
1 Like