Serverless ARN Prefixer Plugin
A Serverless Framework plugin that automatically injects custom ARN properties into your serverless configuration, making it easier to build AWS resource ARNs consistently across your application. Supports both ${arn:*} variable resolvers and ${arn:*} object references for maximum compatibility.
Installation
From npm (Recommended)
npm install @hyperdrive.bot/serverless-arn-prefixer
From GitLab Package Registry (Development)
npm config set @hyperdrive.bot:registry https://gitlab.com/api/v4/projects/PROJECT_ID/packages/npm/
npm install @hyperdrive.bot/serverless-arn-prefixer
Local Development
If developing within the monorepo, no separate installation required.
Usage
Add the plugin to your serverless.yml:
When installed from npm
plugins:
- "@hyperdrive.bot/serverless-arn-prefixer"
When using locally in monorepo
plugins:
- ./packages/serverless/arn-prefixer
Or if using from within the packages/serverless directory:
plugins:
- ./arn-prefixer
Configuration
Runtime Code Generation (Default: Enabled)
Configure runtime file generation in your serverless.yml:
custom:
arnPrefixer:
generateRuntime: true
runtimePath: 'runtime.js'
Disable Runtime Generation:
custom:
arnPrefixer:
generateRuntime: false
Custom Runtime Path:
custom:
arnPrefixer:
runtimePath: 'my-arn-values.js'
What it does
The plugin automatically injects a custom.arn object into your serverless configuration with the following properties:
NEW: ⚡ Runtime Code Generation (Default: Enabled)
The plugin now generates runtime JavaScript and TypeScript files that allow you to import ARN values directly in your Lambda code without environment variables:
import { arnPrefix, globalPrefix, dynamodb } from 'arn-prefixer/runtime'
const tableName = `${arnPrefix}-users`
const tableArn = `${dynamodb}:table/${tableName}`
This provides zero runtime overhead - values are hardcoded strings at build time!
Basic Properties
custom:
arn:
accountId: "123456789012"
stage: "dev"
service: "my-service"
region: "us-east-1"
prefix: "my-service-dev"
regionalPrefix: "us-east-1-my-service-dev"
globalPrefix: "123456789012-us-east-1-my-service-dev"
ARN Builder Properties
custom:
arn:
arnBase: "arn:aws"
accountRegion: "123456789012:us-east-1"
dynamodb: "arn:aws:dynamodb:123456789012:us-east-1"
s3: "arn:aws:s3:123456789012:us-east-1"
lambda: "arn:aws:lambda:123456789012:us-east-1"
iam: "arn:aws:iam:123456789012:us-east-1"
sns: "arn:aws:sns:123456789012:us-east-1"
sqs: "arn:aws:sqs:123456789012:us-east-1"
apigateway: "arn:aws:apigateway:123456789012:us-east-1"
events: "arn:aws:events:123456789012:us-east-1"
logs: "arn:aws:logs:123456789012:us-east-1"
kinesis: "arn:aws:kinesis:123456789012:us-east-1"
firehose: "arn:aws:firehose:123456789012:us-east-1"
stepfunctions: "arn:aws:states:123456789012:us-east-1"
Using the injected values
Once the plugin is loaded, you can reference these values anywhere in your serverless.yml using two methods:
Method 1: Variable Resolver
Use the ${arn:property} syntax:
resources:
Resources:
MyDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${arn:prefix}-users
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${arn:globalPrefix}-assets
functions:
myFunction:
name: ${arn:regionalPrefix}-handler
Method 2: Custom Object (Manual Definition Required)
Use the ${arn:property} syntax (requires manual property definition):
resources:
Resources:
MyDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${arn:prefix}-users
functions:
myFunction:
name: ${arn:regionalPrefix}-handler
⚠️ Important Compatibility Notes:
- Method 1 (
${arn:*}): ✅ Works with this plugin - uses custom variable resolvers
- Method 2 (
${arn:*}): ❌ Cannot work with plugin-injected properties in Serverless v2 due to variable resolution timing
Why Method 2 Doesn't Work With Plugin
Serverless v2 resolves ALL variables BEFORE loading plugins. This means:
${arn:*} tries to resolve during YAML parsing
- Plugin hasn't loaded yet, so no
custom.arn properties exist
- Resolution fails and stops the process
When Method 2 DOES Work
${arn:*} works when properties are statically defined in serverless.yml:
custom:
arn:
accountId: ${env:AWS_ACCOUNT_ID, '123456789012'}
prefix: ${self:service}-${self:provider.stage}
Recommendations
- With this plugin: Use Method 1 (
${arn:*}) syntax
- With serverless-plugin-composer: Define
custom.arn manually and use Method 2 (${arn:*})
- Hybrid approach: Define basic properties manually, let plugin handle complex ARN building
Method 3: Runtime Imports (NEW! ⚡ Zero Runtime Overhead)
Import ARN values directly in your Lambda code:
import { arnPrefix, globalPrefix, dynamodb, s3 } from 'arn-prefixer/runtime'
const { arnPrefix, globalPrefix, dynamodb, s3 } = require('arn-prefixer/runtime')
export const handler = async (event) => {
const tableName = `${arnPrefix}-users`
const bucketName = `${globalPrefix}-assets`
const tableArn = `${dynamodb}:table/${tableName}`
const bucketArn = `${s3}:bucket/${bucketName}`
}
Available Exports:
arnPrefix - service-stage (e.g., "my-service-dev")
globalPrefix - accountId-region-service-stage (e.g., "123456789012-us-east-1-my-service-dev")
regionalPrefix - region-service-stage (e.g., "us-east-1-my-service-dev")
- All AWS service ARN builders:
dynamodb, s3, lambda, sns, sqs, etc.
Method 4: ARN Builders (Serverless Config)
Build complete AWS ARNs easily:
resources:
Resources:
MyDynamoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${arn:prefix}-users
Outputs:
TableArn:
Value: ${arn:dynamodb}:table/${arn:prefix}-users
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${arn:globalPrefix}-assets
Outputs:
BucketArn:
Value: ${arn:s3}:bucket/${arn:globalPrefix}-assets
MyFunction:
Outputs:
FunctionArn:
Value: ${arn:lambda}:function:${arn:prefix}-processor
user-role-statements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
Resource:
- ${arn:dynamodb}:table/${arn:prefix}-*
- ${arn:dynamodb}:table/*/index/*
Common ARN Patterns
DynamoDBTableArn: ${arn:dynamodb}:table/resource
DynamoDBAllTablesArn: ${arn:dynamodb}:table/*
S3BucketArn: ${arn:s3}:bucket/${arn:prefix}-bucket
LambdaFunctionArn: ${arn:lambda}:function:${arn:prefix}-func
SNSTopicArn: ${arn:sns}:${arn:prefix}-topic
SQSQueueArn: ${arn:sqs}:${arn:prefix}-queue
Comparison with Serverless Framework Defaults
Serverless Framework Default Patterns
| CloudFormation Stack | {service}-{stage} | my-service-dev |
| Lambda Functions | {service}-{stage}-{functionName} | my-service-dev-hello |
| API Gateway | {stage}-{service} | dev-my-service |
| IAM Roles | {service}-{stage}-{region}-lambdaRole | my-service-dev-us-east-1-lambdaRole |
| Custom Resources | {LogicalId}-{RandomSuffix} | MyTable-ABC123DEF456 |
ARN-Prefixer Plugin Patterns
${arn:prefix} | {service}-{stage} | my-service-dev |
${arn:regionalPrefix} | {region}-{service}-{stage} | us-east-1-my-service-dev |
${arn:globalPrefix} | {accountId}-{region}-{service}-{stage} | 123456789012-us-east-1-my-service-dev |
Key Advantages
- ✅ Consistency: All resources follow the same naming convention
- ✅ Predictability: No random suffixes, deterministic resource names
- ✅ Uniqueness: Account ID inclusion ensures cross-account uniqueness
- ✅ Multi-region: Region awareness for global deployments
- ✅ Enterprise Ready: Suitable for complex, multi-tenant architectures
Account ID Resolution
The plugin will attempt to get the AWS Account ID in the following order:
- Environment Variable: If
AWS_ACCOUNT_ID is set, it will use that value
- AWS STS: If the environment variable is not set, it will call AWS STS
getCallerIdentity() to retrieve the account ID
- Error: If both methods fail, the plugin will throw an error and stop deployment
Important: You must either set the AWS_ACCOUNT_ID environment variable or have valid AWS credentials configured. The plugin will not proceed with deployment if it cannot determine the AWS Account ID.
Compatibility
Tested Versions
| 2.72.4 | ✅ Fully Tested | Prefix properties + ARN builders + Error handling |
| 3.38.0 | ✅ Fully Tested | Prefix properties + ARN builders + Error handling |
| 4.18.2 | ✅ Fully Tested | Prefix properties + ARN builders + Error handling |
Requirements:
- Serverless Framework: 2.0.0 and above (supports v2, v3, and v4)
- Node.js: 14.0.0 and above
Plugin Execution
The plugin runs during the after:aws:common:validate:validate hook, ensuring that all properties are available before your resources are processed.
Example Output
Successful execution:
ARN Prefixer: Injected custom.arn properties
- accountId: 123456789012
- stage: dev
- service: my-service
- region: us-east-1
- prefix: my-service-dev
- regionalPrefix: us-east-1-my-service-dev
- globalPrefix: 123456789012-us-east-1-my-service-dev
Error when Account ID cannot be determined:
ARN Prefixer Plugin Error: Cannot determine AWS Account ID.
Please either:
1. Set the AWS_ACCOUNT_ID environment variable, or
2. Ensure you have valid AWS credentials configured
AWS STS Error: The security token included in the request is expired