55

I want to build an ARN in my file dynamically, but I need to get my current AccountId. How can I access it as a variable?

For example:

example: arn:aws:states:${region}:${accountId}:stateMachine:${self:service}-${self:custom.stage}-example

What is the proper way to reference the current region and accountId?

justin.m.chase
  • 13,061
  • 8
  • 52
  • 100

5 Answers5

51

This is now supported natively in Serverless Framework.

functions example

  functions:
    hello:
      handler: my-function.handler
      environment:
        var: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*:*:*'

iam role example

  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - dynamodb:*
          Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${AWS::StackName}-*

See Pseudo Parameters Reference for the official docs.

V Maharajh
  • 9,013
  • 5
  • 30
  • 31
  • 1
    This worked for me. This should be higher up since its a native solution without relying on plugins. – Bihan Viranga Mar 18 '21 at 09:27
  • 3
    For those of you who try to use this solution, make sure to include the `!Sub` in the front. – C.Lee Apr 29 '21 at 21:32
  • 1
    Also see the [AWS CloudFormation Pseudo parameters reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html) in addition to the serverless docs link in the answer. – Shane Bishop Jun 07 '22 at 13:51
26

This is now supported natively since version 2.3.0.

Just reference it via ${aws:accountId}. You can also reference region via ${aws:region}. Documentation here: https://www.serverless.com/framework/docs/providers/aws/guide/variables#referencing-aws-specific-variables

service: new-service
provider: aws

functions:
  func1:
    name: function-1
    handler: handler.func1
    environment:
      ACCOUNT_ID: ${aws:accountId}
      REGION: ${aws:region}
DV82XL
  • 5,350
  • 5
  • 30
  • 59
John Paulo Rodriguez
  • 1,280
  • 18
  • 21
  • Is this different than the accepted answer? https://stackoverflow.com/a/64867520/12958 – justin.m.chase Jul 09 '21 at 19:00
  • 2
    the accepted answer uses the Cloudformation pseudo parameters reference* (`AWS::AccountId` w/ double colon) with the help of `!Sub` function. My answer natively supports the `${aws:accountId}` but only supported on serverless version >= 2.3.0 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html – John Paulo Rodriguez Jul 11 '21 at 06:43
  • The use of the `!Sub` function in the previous answer is irrelevant. Using the updated `aws:accountId` is indeed better tho. – V Maharajh Jun 30 '22 at 22:34
  • I was able to switch over the ones you mentioned, but ${aws:stackName} doesn't seem to work. – V Maharajh Jul 02 '22 at 05:43
  • Yeah... but... BIG but... doesn't work with serverless offline !!! – Lqueryvg Jan 12 '23 at 14:58
24

There's a handy serverless plugin https://www.npmjs.com/package/serverless-pseudo-parameters that adds the ability to reference aws parameters such as region and account id that i've just started using to much success.

Sam J
  • 714
  • 1
  • 9
  • 15
  • I haven't vetted this plugin yet but this seems like the best answer to be honest, switched to be the correct answer. – justin.m.chase Jun 16 '17 at 01:44
  • You can also use !Ref to access them. – Victor Martinez Apr 22 '20 at 10:05
  • That package says that it is deprecated and supported natively in serverless framework now. I'm trying to figure out how to use it natively... – V Maharajh Nov 17 '20 at 00:04
  • @Madeo, it works. Check out my answer below: https://stackoverflow.com/a/64867520/1495198 – V Maharajh Mar 15 '21 at 16:05
  • @Madeo, I have it working for an iam policy: `Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${AWS::StackName}-*`. You can see the full serverless.yml file here: https://github.com/vivmaha/blog-server/blob/main/serverless.yml – V Maharajh Mar 16 '21 at 15:55
  • @VivekMaharajh you might have two versions of serverless installed? one locally and one globally? might be worth double checking – Sam J Mar 17 '21 at 03:51
  • @Madeo, so if you clone my repo and try `npm run sls -- package --stage dev`, it fails for you? SamJ's suggestion is promising as well, I assumed they meant to tell you that not me. – V Maharajh Mar 17 '21 at 17:14
9

Serverless itself cannot reference those variables since those are defined within CloudFormation, but not exposed in serverless.

If you need those in the resources section you can directly access them via "Ref"-call.

AWS CloudFormation Pseudo-variables

If you need those variable as function environment variables, you can overwrite the serverless generated function code with CloudFormation code.

So to achieve this, you must modify you serverless.yml by the following pattern.

functions:
  hello:
    handler: handler.hello
resources:
  Resources:
   HelloLambdaFunction:
     Type: AWS::Lambda::Function
     Properties:
       Environment:
         Variables:
           accountId:
             Ref: AWS::AccountId
           region:
             Ref: AWS::Region
           arn:
             Fn::Join:
               - ""
               - - "arn:aws:states:"
                 - Ref: AWS::Region
                 - ":"
                 - Ref: AWS::AccountId
                 - ":stateMachine:"
                 - ${self:service}
                 - "-"
                 - ${self:custom.stage}
                 - "-example"
jens walter
  • 13,269
  • 2
  • 56
  • 54
  • Please note that this answer is outdated. This is indeed supported in serverless framework now as I explain in [this answer](https://stackoverflow.com/a/64867520/1495198). – V Maharajh Mar 18 '21 at 17:12
6

EDIT: this question is probably outdated. Consider this comment and this answer.


AWS CloudFormation offers some variables like AWS::AccountIdand AWS::Region, but you can't use them in the serverless.yml file like ${AWS::AccountId}. Those are not supported.

@jens answer is right. You must use the CloudFormation syntax. In the example below, I provide another way to use CloudFormation.

service: testing-aws-account-id

provider:
  name: aws
  runtime: nodejs4.3
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "iot:Publish"
      Resource: 'Fn::Join: ["", [ "aws:iot:", { "Ref": "AWS::Region" }, ":", { Ref: "AWS::AccountId" }, ":topic/foo" ]]'

functions:
  publishIot:
    handler: handler.publishIot

The line:

 Resource: 'Fn::Join: ["", [ "aws:iot:", { "Ref": "AWS::Region" }, ":", { Ref: "AWS::AccountId" }, ":topic/foo" ]]'

is the same of hard-coding the region and account id:

Resource: "arn:aws:iot:us-east-1:1234567890:topic/foo"    
Zanon
  • 29,231
  • 20
  • 113
  • 126
  • Could that line be replaced with `Resource: '!Sub arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/foo'` ? – BamaPookie Dec 28 '17 at 16:51
  • 2
    @BamaPookie, I don't think so. It should work only if you add [this plugin](https://www.npmjs.com/package/serverless-pseudo-parameters). – Zanon Dec 28 '17 at 23:27
  • 2
    I get `Partition "" is not valid for resource "arn::Join: ["", [ "arn:` – SteveCoffman Sep 07 '18 at 21:13
  • 1
    @BamaPookie you really helped me out here with this. This plugin is exactly what I need! – Sigex Jul 28 '20 at 17:48
  • 1
    Please note that this answer is outdated. This is indeed supported in serverless framework now as I explain in [this answer](https://stackoverflow.com/a/64867520/1495198). – V Maharajh Mar 18 '21 at 17:11
  • 1
    @VivekMaharajh I don't have time to test this, but I've upvoted your answer and edited mine to reference yours. Thanks – Zanon Mar 22 '21 at 09:04