Reference AWS ARN in serverless.ts file

How can I reference the ARN of a resource in a serverless.ts file? Details below…

I created a new Serverless project with the command: serverless create --template aws-nodejs-typescript. I noticed that I am supplied with a serverless.ts file now rather than a serverless.yml file.

In the old serverless.yml file I can get a resource’s ARN by using the following code:

custom:
  AuctionsTable:
  arn: !GetAtt AuctionsTable.Arn

I can reference that code elsewhere in the serverless.yml with the following code:

  Resource:
  - ${self:custom.AuctionsTable.arn}

When I use the sls print command, that code becomes CF code that looks like this:

      Resource:
      - 'Fn::GetAtt':
          - AuctionsTable
          - Arn

With the serverless.ts file, that same code does not become the same CF code. The following code:

  custom: {
    auctionsTable: {
      arn: "!GetAtt AuctionsTable.Arn"
  }

Becomes the following after sls print:

      Resource:
      - '!GetAtt AuctionsTable.Arn'

Which produces the following error when trying to deploy:

Resource !GetAtt AuctionsTable.Arn must be in ARN format or "*".

It seems like Serverless framework isn’t converting:

!GetAtt AuctionsTable.Arn

to:

          Resource:
          - 'Fn::GetAtt':
            - AuctionsTable
            - Arn

Any ideas on how to workaround this? Or am I taking the wrong approach?

I learned that you can reference an ARN using the following syntax:

  Resource: {
    "Fn::GetAtt": ["AuctionsTable, "Arn"],
  },

The file awsProvider.d.ts proved to be helpful here. The IamRoleStatement shows an indexable type can be provided to the Resource field:

    interface IamRoleStatement {
      Effect: 'Allow' | 'Deny';
      Sid?: string;
      Condition?: {
          [key: string]: any;
      };
      Action?: string | string[] | { [key: string]: any };
      NotAction?: string | string[] | { [key: string]: any };
      Resource?: string | string[] | { [key: string]: any };
      NotResource?: string | string[] | { [key: string]: any };
  }

Just a quick note - @scott 's answer is right on (there’s a missing quote in his Resource example, otherwise perfect).

If you are using SNS you can’t call Fn::GetAtt and need to do this:

iamRoleStatements: [
  {
    Effect: 'Allow',
    Action: ['sns:Publish'],
    Resource: {
      "Ref": "doMagic",
    },
  }
]

where doMagic is the resource. Because GetAtt is not available on SNS for obtaining the ARN.

Hopefully that helps someone else out!

1 Like

Hi, I am having trouble getting this work. I am trying to attach lambda func with dynamo stream. could you please help. It would be great if you can share any documentation for serverless.ts file

handleMdmEventStream: {
      name: '${self:custom.name}-handleMdmEventStream',
      handler: 'src/triggers/mdm-stream-trigger.handler',
      events: [
        {
          stream: {
            arn: {
              "Fn::GetAtt": ["loggers", "StreamArn"]
            },
          }
        }
      ]
    },

Using the typescript node.js serverless template, I was able to use a Kinesis Stream Arn using the following syntax:

functions: {
    ingestion: {
      handler: 'handler.ingestStream',
      events: [
        {
          stream: {
            type: 'kinesis',
            arn: { 'Fn::GetAtt': ['SuperSweetStream', 'Arn'] },
          },
        }
      ]
    }
  },
resources: {
    Resources: {
      'SuperSweetStream': {
        'Type' : 'AWS::Kinesis::Stream',
        'Properties' : {
            'Name' : '${self:service}-stream',
            'RetentionPeriodHours' : 24,
            'ShardCount' : 3,
          }
      }
    }
  }
1 Like

@cgradwohl can you please also share the Kinesis stream definition you used? Thanks!

Does anyone know how to reference AWS ARN in fileSystemConfig for Serverless as detailed in this GH issue?