Backstage plugin which pulls entities from AWS CloudFormation stacks metadata.
- Pull arbitrary number of Backstage entities from CloudFormation stack's Metadata
- Scan whole CloudFormation region
- Use multiple AWS profiles/accounts
- Use variables inside the entities - reference CloudFormation Stack Outputs or Region
- Setup AWS profile credentials on your machine
# ~/.aws/credentials
[myProfile]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Learn more in AWS documentation here.
- Add Backstage notation to your CloudFormation template's Metadata section
Make sure to put the notation to correct path: Metadata.Backstage.Entities
.
AWSTemplateFormatVersion: 2010-09-09
Resources:
MyLambdaFunction:
Type: 'AWS::Lambda::Function'
Properties:
FunctionName: my-lambda
Metadata:
Backstage:
Entities:
- apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: petstore
namespace: external-systems
description: Petstore
spec:
type: service
lifecycle: experimental
owner: 'group:pet-managers'
providesApis:
- petstore
- internal/streetlights
- hello-world
- apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: petstore
description: The Petstore API
spec:
type: openapi
lifecycle: production
owner: petstore@example.com
definition:
$text: 'https://petstore.swagger.io/v2/swagger.json'
- If you have a standalone app (you didn't clone this repo), then do
# From your Backstage root directory
$ cd packages/backend
$ yarn add backstage-aws-cloudformation-plugin
- Add the
CloudFormationRegionProcessor
andCloudFormationStackProcessor
processors your catalog builder
// In packages/backend/src/plugins/catalog.ts
+import {
+ CloudFormationRegionProcessor,
+ CloudFormationStackProcessor,
+} from 'backstage-aws-cloudformation-plugin';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
+ builder.addProcessor(new CloudFormationStackProcessor(env.config));
+ builder.addProcessor(new CloudFormationRegionProcessor(env.config));
const {
entitiesCatalog,
locationsCatalog,
locationService,
processingEngine,
locationAnalyzer,
} = await builder.build();
- Run Backstage with AWS_SDK_LOAD_CONFIG
In order for AWS SDK inside the plugin to work with AWS profile configuration in ~/.aws/config
, make sure to start backstage with AWS_SDK_LOAD_CONFIG=true
environment variable.
...
"scripts": {
"dev": "AWS_SDK_LOAD_CONFIG=true concurrently \"yarn start\" \"yarn start-backend\"",
"start": "AWS_SDK_LOAD_CONFIG=true yarn workspace app start",
"start-backend": "AWS_SDK_LOAD_CONFIG=true yarn workspace backend start",
...
- Optionaly add default profile configuration
# In app-config.yaml
integrations:
aws:
profile: purple-technology
- Add Locations
# In app-config.yaml
catalog:
locations:
# Pull single stack from the profile "myProfile"
- type: aws:cloudformation:stack
target: myProfile@arn:aws:cloudformation:ap-southeast-1:123456789000:stack/some-stack/123-345-12-1235-123123
# Pull single stack from the default profile
- type: aws:cloudformation:stack
target: arn:aws:cloudformation:eu-central-1:123456789000:stack/other-stack/532-123-59-593-19481
# Pull whole region from the "myProfile" profile
- type: aws:cloudformation:region
target: myProfile@ap-southeast-1
# Pull whole region from the default profile
- type: aws:cloudformation:region
target: eu-central-1
Accepts as a target
ARN of the CloudFormation stack and optionally also name of the profile separated by @
.
[profileName@]stack_arn
Accepts as a target
ID of the AWS region and optionally also name of the profile separated by @
.
[profileName@]region-name-1
Since it's not possible to use intrinsic functions (Ref
, Fn::GetAtt
, etc.) inside Metadata
, we've solved it via custom variables syntax.
When the entities are loaded from the Metadata
, any variables inside are processed and replaced with appropriate values - if found.
You can escape the variable expression via \
.
For example this variable won't get replaced:
\${Outputs.SomeVariable}
Type | Example Input | Example Output | Description |
---|---|---|---|
Region | description: "Service in ${Region} region" |
description: "Service in eu-central-1 region" |
Provides region of the stack. |
AccountId | title: AWS Account ID is ${AccountId} |
title: AWS Account ID is 123456789000 |
Provides ID of the AWS account. |
StackId | title: Stack ARN is ${StackId} |
title: Stack ARN is arn:aws:cloudformation:ap-southeast-1:123456789000:stack/some-stack/123-345-12-1235-123123 |
Provides stack ID (ARN). |
StackName | title: Stack Name is ${StackName} |
title: Stack Name is some-stack |
Provides stack name. |
Outputs | name: "lambda-${Outputs.GetClientsLambdaName}" |
name: "lambda-get-clients-prod" |
Provides Output value from the stack. |
- The plugin has built-in mechanism for dealing with throttling, but in case of indexing a whole region be careful with the number of stacks in the region