SNS resource tagging enables you to organize, track, and manage SNS resources using key-value pairs for cost allocation, access control, and operational management.
Adds or updates tags for SNS resources including topics, subscriptions, and platform applications.
/**
* Adds tags to an Amazon SNS resource
* Tags are key-value pairs that help organize and manage resources
*/
class TagResourceCommand {
constructor(input: TagResourceRequest);
}
interface TagResourceRequest {
/** ARN of the resource to tag */
ResourceArn: string;
/** List of tags to add or update */
Tags: Tag[];
}
interface TagResourceResponse {
/** Response metadata */
ResponseMetadata?: any;
}
interface Tag {
/** Tag key (required) */
Key: string;
/** Tag value (required) */
Value: string;
}Usage Examples:
import { SNSClient, TagResourceCommand } from "@aws-sdk/client-sns";
const client = new SNSClient({ region: "us-east-1" });
// Tag a topic with environment and team information
await client.send(new TagResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
Tags: [
{ Key: "Environment", Value: "Production" },
{ Key: "Team", Value: "Backend" },
{ Key: "Project", Value: "UserNotifications" },
{ Key: "CostCenter", Value: "Engineering" }
]
}));
// Tag a subscription
await client.send(new TagResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic:subscription-id",
Tags: [
{ Key: "Protocol", Value: "email" },
{ Key: "Priority", Value: "high" },
{ Key: "Owner", Value: "admin@example.com" }
]
}));
// Tag a platform application
await client.send(new TagResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:app/APNS/MyApp",
Tags: [
{ Key: "Platform", Value: "iOS" },
{ Key: "AppVersion", Value: "2.1.0" },
{ Key: "Environment", Value: "Production" }
]
}));Removes specified tags from SNS resources.
/**
* Removes tags from an Amazon SNS resource
* Removes the specified tag keys and their values
*/
class UntagResourceCommand {
constructor(input: UntagResourceRequest);
}
interface UntagResourceRequest {
/** ARN of the resource to untag */
ResourceArn: string;
/** List of tag keys to remove */
TagKeys: string[];
}
interface UntagResourceResponse {
/** Response metadata */
ResponseMetadata?: any;
}Usage Examples:
// Remove specific tags from a topic
await client.send(new UntagResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
TagKeys: ["Environment", "CostCenter"]
}));
// Remove all specified tags from a subscription
await client.send(new UntagResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic:subscription-id",
TagKeys: ["Priority", "Owner"]
}));Retrieves all tags associated with a specific SNS resource.
/**
* Returns a list of tags associated with an Amazon SNS resource
* Shows all current key-value pairs for the resource
*/
class ListTagsForResourceCommand {
constructor(input: ListTagsForResourceRequest);
}
interface ListTagsForResourceRequest {
/** ARN of the resource */
ResourceArn: string;
}
interface ListTagsForResourceResponse {
/** List of tags associated with the resource */
Tags?: Tag[];
}Usage Examples:
// List all tags for a topic
const topicTags = await client.send(new ListTagsForResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic"
}));
topicTags.Tags?.forEach(tag => {
console.log(`${tag.Key}: ${tag.Value}`);
});
// List tags for a platform application
const appTags = await client.send(new ListTagsForResourceCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:app/APNS/MyApp"
}));
console.log("Platform Application Tags:");
appTags.Tags?.forEach(tag => {
console.log(` ${tag.Key}: ${tag.Value}`);
});Organize resources by environment for clear separation and management:
const tagResourceByEnvironment = async (resourceArn: string, environment: string) => {
const baseTags = [
{ Key: "Environment", Value: environment },
{ Key: "ManagedBy", Value: "Infrastructure" },
{ Key: "CreatedDate", Value: new Date().toISOString().split('T')[0] }
];
// Add environment-specific tags
const environmentTags = environment === "Production"
? [
{ Key: "Backup", Value: "Required" },
{ Key: "Monitoring", Value: "Enhanced" },
{ Key: "SLA", Value: "Critical" }
]
: [
{ Key: "Backup", Value: "Optional" },
{ Key: "Monitoring", Value: "Basic" },
{ Key: "AutoShutdown", Value: "Enabled" }
];
await client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: [...baseTags, ...environmentTags]
}));
};
// Usage
await tagResourceByEnvironment(
"arn:aws:sns:us-east-1:123456789012:ProductionAlerts",
"Production"
);Implement comprehensive cost tracking with standardized tags:
const applyCostAllocationTags = async (
resourceArn: string,
project: string,
team: string,
costCenter: string
) => {
await client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: [
{ Key: "Project", Value: project },
{ Key: "Team", Value: team },
{ Key: "CostCenter", Value: costCenter },
{ Key: "BillingContact", Value: `${team.toLowerCase()}@company.com` },
{ Key: "BudgetCode", Value: `${costCenter}-${project}` }
]
}));
};
// Apply cost allocation tags to multiple resources
const resources = [
"arn:aws:sns:us-east-1:123456789012:UserNotifications",
"arn:aws:sns:us-east-1:123456789012:OrderAlerts",
"arn:aws:sns:us-east-1:123456789012:SystemAlerts"
];
for (const resourceArn of resources) {
await applyCostAllocationTags(
resourceArn,
"ECommercePlatform",
"Backend",
"ENG-001"
);
}Tag resources with operational metadata for automation and management:
const applyOperationalTags = async (resourceArn: string) => {
await client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: [
{ Key: "Owner", Value: "platform-team@company.com" },
{ Key: "SupportLevel", Value: "24x7" },
{ Key: "BackupSchedule", Value: "daily" },
{ Key: "PatchGroup", Value: "production-sns" },
{ Key: "SecurityScan", Value: "enabled" },
{ Key: "ComplianceRequired", Value: "HIPAA,SOX" },
{ Key: "DataClassification", Value: "confidential" },
{ Key: "AutomationEnabled", Value: "true" }
]
}));
};Efficiently tag multiple resources with common patterns:
const bulkTagResources = async (
resourceArns: string[],
commonTags: Tag[]
) => {
const tagPromises = resourceArns.map(resourceArn =>
client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: commonTags
}))
);
try {
await Promise.all(tagPromises);
console.log(`Successfully tagged ${resourceArns.length} resources`);
} catch (error) {
console.error("Error in bulk tagging:", error);
// Retry failed resources individually
for (const resourceArn of resourceArns) {
try {
await client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: commonTags
}));
console.log(`✓ Tagged: ${resourceArn}`);
} catch (err) {
console.error(`✗ Failed to tag: ${resourceArn}`, err.message);
}
}
}
};
// Usage
const migrationTags = [
{ Key: "Migration", Value: "Q1-2024" },
{ Key: "MigrationStatus", Value: "pending" },
{ Key: "MigrationOwner", Value: "cloud-team" }
];
await bulkTagResources([
"arn:aws:sns:us-east-1:123456789012:Topic1",
"arn:aws:sns:us-east-1:123456789012:Topic2",
"arn:aws:sns:us-east-1:123456789012:Topic3"
], migrationTags);Ensure consistent tagging across resources:
interface TaggingStandards {
required: string[];
allowedValues: { [key: string]: string[] };
patterns: { [key: string]: RegExp };
}
const taggingStandards: TaggingStandards = {
required: ["Environment", "Team", "Project"],
allowedValues: {
"Environment": ["Development", "Staging", "Production"],
"Team": ["Frontend", "Backend", "DevOps", "QA"],
"Priority": ["Low", "Medium", "High", "Critical"]
},
patterns: {
"CostCenter": /^[A-Z]{3}-\d{3}$/,
"Email": /^[^\s@]+@[^\s@]+\.[^\s@]+$/
}
};
const validateAndTagResource = async (
resourceArn: string,
proposedTags: Tag[]
) => {
// Check required tags
const tagKeys = proposedTags.map(tag => tag.Key);
const missingRequired = taggingStandards.required.filter(
required => !tagKeys.includes(required)
);
if (missingRequired.length > 0) {
throw new Error(`Missing required tags: ${missingRequired.join(', ')}`);
}
// Validate tag values
for (const tag of proposedTags) {
// Check allowed values
if (taggingStandards.allowedValues[tag.Key]) {
if (!taggingStandards.allowedValues[tag.Key].includes(tag.Value)) {
throw new Error(
`Invalid value '${tag.Value}' for tag '${tag.Key}'. ` +
`Allowed values: ${taggingStandards.allowedValues[tag.Key].join(', ')}`
);
}
}
// Check patterns
if (taggingStandards.patterns[tag.Key]) {
if (!taggingStandards.patterns[tag.Key].test(tag.Value)) {
throw new Error(
`Tag '${tag.Key}' value '${tag.Value}' does not match required pattern`
);
}
}
}
// Apply tags if validation passes
await client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: proposedTags
}));
console.log(`Successfully tagged resource with validated tags`);
};Find resources based on tag criteria:
import { ListTopicsCommand } from "@aws-sdk/client-sns";
const findResourcesByTags = async (
targetTags: { [key: string]: string }
) => {
const topics = await client.send(new ListTopicsCommand());
const matchingResources: string[] = [];
for (const topic of topics.Topics || []) {
if (topic.TopicArn) {
const tags = await client.send(new ListTagsForResourceCommand({
ResourceArn: topic.TopicArn
}));
const resourceTags = tags.Tags || [];
const matches = Object.entries(targetTags).every(([key, value]) =>
resourceTags.some(tag => tag.Key === key && tag.Value === value)
);
if (matches) {
matchingResources.push(topic.TopicArn);
}
}
}
return matchingResources;
};
// Find all production resources owned by backend team
const productionBackendResources = await findResourcesByTags({
"Environment": "Production",
"Team": "Backend"
});
console.log("Production Backend Resources:", productionBackendResources);Regular maintenance of resource tags:
const cleanupResourceTags = async (resourceArn: string) => {
const tags = await client.send(new ListTagsForResourceCommand({
ResourceArn: resourceArn
}));
const tagsToRemove: string[] = [];
const tagsToUpdate: Tag[] = [];
for (const tag of tags.Tags || []) {
// Remove deprecated tags
if (tag.Key.startsWith("deprecated-")) {
tagsToRemove.push(tag.Key);
}
// Standardize case
if (tag.Key === "environment" || tag.Key === "ENVIRONMENT") {
tagsToRemove.push(tag.Key);
tagsToUpdate.push({ Key: "Environment", Value: tag.Value });
}
// Remove empty values
if (!tag.Value || tag.Value.trim() === "") {
tagsToRemove.push(tag.Key);
}
}
// Remove unwanted tags
if (tagsToRemove.length > 0) {
await client.send(new UntagResourceCommand({
ResourceArn: resourceArn,
TagKeys: tagsToRemove
}));
}
// Add standardized tags
if (tagsToUpdate.length > 0) {
await client.send(new TagResourceCommand({
ResourceArn: resourceArn,
Tags: tagsToUpdate
}));
}
};Implement automatic tagging when creating resources:
import { CreateTopicCommand } from "@aws-sdk/client-sns";
const createTopicWithStandardTags = async (
topicName: string,
customTags: Tag[] = []
) => {
// Create the topic first
const createResult = await client.send(new CreateTopicCommand({
Name: topicName
}));
if (!createResult.TopicArn) {
throw new Error("Failed to create topic");
}
// Apply standard tags
const standardTags: Tag[] = [
{ Key: "CreatedBy", Value: "AutomatedSystem" },
{ Key: "CreatedDate", Value: new Date().toISOString().split('T')[0] },
{ Key: "ResourceType", Value: "SNS-Topic" },
{ Key: "ManagedBy", Value: "Infrastructure" }
];
await client.send(new TagResourceCommand({
ResourceArn: createResult.TopicArn,
Tags: [...standardTags, ...customTags]
}));
return createResult.TopicArn;
};
// Usage
const topicArn = await createTopicWithStandardTags("NewProductTopic", [
{ Key: "Environment", Value: "Production" },
{ Key: "Team", Value: "Backend" },
{ Key: "Project", Value: "ProductCatalog" }
]);Use tags for resource-based access control in IAM policies:
IAM Policy Example:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish",
"sns:Subscribe"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"sns:ResourceTag/Team": "${aws:PrincipalTag/Team}",
"sns:ResourceTag/Environment": "Production"
}
}
}
]
}This policy allows users to only interact with SNS resources that: